Merge git://git.kernel.org/pub/scm/linux/kernel/git/cmetcalf/linux-tile
Pull tile updates from Chris Metcalf: "These are a smattering of minor changes from Tilera and other folks, mostly in the ptrace area." * git://git.kernel.org/pub/scm/linux/kernel/git/cmetcalf/linux-tile: arch/tile: set CORE_DUMP_USE_REGSET on tile arch/tile: implement arch_ptrace using user_regset on tile arch/tile: implement user_regset interface on tile arch/tile: clean up tile-specific PTRACE_SETOPTIONS arch/tile: provide PT_FLAGS_COMPAT value in pt_regs tile/PCI: use for_each_pci_dev to simplify the code tilegx: remove __init from pci fixup hook
This commit is contained in:
commit
5b3040a48b
|
@ -170,4 +170,6 @@ do { \
|
||||||
|
|
||||||
#endif /* CONFIG_COMPAT */
|
#endif /* CONFIG_COMPAT */
|
||||||
|
|
||||||
|
#define CORE_DUMP_USE_REGSET
|
||||||
|
|
||||||
#endif /* _ASM_TILE_ELF_H */
|
#endif /* _ASM_TILE_ELF_H */
|
||||||
|
|
|
@ -24,8 +24,7 @@ typedef unsigned long pt_reg_t;
|
||||||
#include <uapi/asm/ptrace.h>
|
#include <uapi/asm/ptrace.h>
|
||||||
|
|
||||||
#define PTRACE_O_MASK_TILE (PTRACE_O_TRACEMIGRATE)
|
#define PTRACE_O_MASK_TILE (PTRACE_O_TRACEMIGRATE)
|
||||||
#define PT_TRACE_MIGRATE 0x00080000
|
#define PT_TRACE_MIGRATE PT_EVENT_FLAG(PTRACE_EVENT_MIGRATE)
|
||||||
#define PT_TRACE_MASK_TILE (PT_TRACE_MIGRATE)
|
|
||||||
|
|
||||||
/* Flag bits in pt_regs.flags */
|
/* Flag bits in pt_regs.flags */
|
||||||
#define PT_FLAGS_DISABLE_IRQ 1 /* on return to kernel, disable irqs */
|
#define PT_FLAGS_DISABLE_IRQ 1 /* on return to kernel, disable irqs */
|
||||||
|
|
|
@ -81,8 +81,14 @@ struct pt_regs {
|
||||||
#define PTRACE_SETFPREGS 15
|
#define PTRACE_SETFPREGS 15
|
||||||
|
|
||||||
/* Support TILE-specific ptrace options, with events starting at 16. */
|
/* Support TILE-specific ptrace options, with events starting at 16. */
|
||||||
#define PTRACE_O_TRACEMIGRATE 0x00010000
|
|
||||||
#define PTRACE_EVENT_MIGRATE 16
|
#define PTRACE_EVENT_MIGRATE 16
|
||||||
|
#define PTRACE_O_TRACEMIGRATE (1 << PTRACE_EVENT_MIGRATE)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Flag bits in pt_regs.flags that are part of the ptrace API.
|
||||||
|
* We start our numbering higher up to avoid confusion with the
|
||||||
|
* non-ABI kernel-internal values that use the low 16 bits.
|
||||||
|
*/
|
||||||
|
#define PT_FLAGS_COMPAT 0x10000 /* process is an -m32 compat process */
|
||||||
|
|
||||||
#endif /* _UAPI_ASM_TILE_PTRACE_H */
|
#endif /* _UAPI_ASM_TILE_PTRACE_H */
|
||||||
|
|
|
@ -245,7 +245,7 @@ static void __devinit fixup_read_and_payload_sizes(void)
|
||||||
u16 new_values;
|
u16 new_values;
|
||||||
|
|
||||||
/* Scan for the smallest maximum payload size. */
|
/* Scan for the smallest maximum payload size. */
|
||||||
while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
|
for_each_pci_dev(dev) {
|
||||||
u32 devcap;
|
u32 devcap;
|
||||||
int max_payload;
|
int max_payload;
|
||||||
|
|
||||||
|
@ -260,7 +260,7 @@ static void __devinit fixup_read_and_payload_sizes(void)
|
||||||
|
|
||||||
/* Now, set the max_payload_size for all devices to that value. */
|
/* Now, set the max_payload_size for all devices to that value. */
|
||||||
new_values = (max_read_size << 12) | (smallest_max_payload << 5);
|
new_values = (max_read_size << 12) | (smallest_max_payload << 5);
|
||||||
while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL)
|
for_each_pci_dev(dev)
|
||||||
pcie_capability_clear_and_set_word(dev, PCI_EXP_DEVCTL,
|
pcie_capability_clear_and_set_word(dev, PCI_EXP_DEVCTL,
|
||||||
PCI_EXP_DEVCTL_PAYLOAD | PCI_EXP_DEVCTL_READRQ,
|
PCI_EXP_DEVCTL_PAYLOAD | PCI_EXP_DEVCTL_READRQ,
|
||||||
new_values);
|
new_values);
|
||||||
|
|
|
@ -1047,8 +1047,7 @@ int pcibios_enable_device(struct pci_dev *dev, int mask)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Called for each device after PCI setup is done. */
|
/* Called for each device after PCI setup is done. */
|
||||||
static void __init
|
static void pcibios_fixup_final(struct pci_dev *pdev)
|
||||||
pcibios_fixup_final(struct pci_dev *pdev)
|
|
||||||
{
|
{
|
||||||
set_dma_ops(&pdev->dev, gx_pci_dma_map_ops);
|
set_dma_ops(&pdev->dev, gx_pci_dma_map_ops);
|
||||||
set_dma_offset(&pdev->dev, TILE_PCI_MEM_MAP_BASE_OFFSET);
|
set_dma_offset(&pdev->dev, TILE_PCI_MEM_MAP_BASE_OFFSET);
|
||||||
|
|
|
@ -19,7 +19,10 @@
|
||||||
#include <linux/kprobes.h>
|
#include <linux/kprobes.h>
|
||||||
#include <linux/compat.h>
|
#include <linux/compat.h>
|
||||||
#include <linux/uaccess.h>
|
#include <linux/uaccess.h>
|
||||||
|
#include <linux/regset.h>
|
||||||
|
#include <linux/elf.h>
|
||||||
#include <asm/traps.h>
|
#include <asm/traps.h>
|
||||||
|
#include <arch/chip.h>
|
||||||
|
|
||||||
void user_enable_single_step(struct task_struct *child)
|
void user_enable_single_step(struct task_struct *child)
|
||||||
{
|
{
|
||||||
|
@ -45,6 +48,100 @@ void ptrace_disable(struct task_struct *child)
|
||||||
clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
|
clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Get registers from task and ready the result for userspace.
|
||||||
|
* Note that we localize the API issues to getregs() and putregs() at
|
||||||
|
* some cost in performance, e.g. we need a full pt_regs copy for
|
||||||
|
* PEEKUSR, and two copies for POKEUSR. But in general we expect
|
||||||
|
* GETREGS/PUTREGS to be the API of choice anyway.
|
||||||
|
*/
|
||||||
|
static char *getregs(struct task_struct *child, struct pt_regs *uregs)
|
||||||
|
{
|
||||||
|
*uregs = *task_pt_regs(child);
|
||||||
|
|
||||||
|
/* Set up flags ABI bits. */
|
||||||
|
uregs->flags = 0;
|
||||||
|
#ifdef CONFIG_COMPAT
|
||||||
|
if (task_thread_info(child)->status & TS_COMPAT)
|
||||||
|
uregs->flags |= PT_FLAGS_COMPAT;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return (char *)uregs;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Put registers back to task. */
|
||||||
|
static void putregs(struct task_struct *child, struct pt_regs *uregs)
|
||||||
|
{
|
||||||
|
struct pt_regs *regs = task_pt_regs(child);
|
||||||
|
|
||||||
|
/* Don't allow overwriting the kernel-internal flags word. */
|
||||||
|
uregs->flags = regs->flags;
|
||||||
|
|
||||||
|
/* Only allow setting the ICS bit in the ex1 word. */
|
||||||
|
uregs->ex1 = PL_ICS_EX1(USER_PL, EX1_ICS(uregs->ex1));
|
||||||
|
|
||||||
|
*regs = *uregs;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum tile_regset {
|
||||||
|
REGSET_GPR,
|
||||||
|
};
|
||||||
|
|
||||||
|
static int tile_gpr_get(struct task_struct *target,
|
||||||
|
const struct user_regset *regset,
|
||||||
|
unsigned int pos, unsigned int count,
|
||||||
|
void *kbuf, void __user *ubuf)
|
||||||
|
{
|
||||||
|
struct pt_regs regs;
|
||||||
|
|
||||||
|
getregs(target, ®s);
|
||||||
|
|
||||||
|
return user_regset_copyout(&pos, &count, &kbuf, &ubuf, ®s, 0,
|
||||||
|
sizeof(regs));
|
||||||
|
}
|
||||||
|
|
||||||
|
static int tile_gpr_set(struct task_struct *target,
|
||||||
|
const struct user_regset *regset,
|
||||||
|
unsigned int pos, unsigned int count,
|
||||||
|
const void *kbuf, const void __user *ubuf)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
struct pt_regs regs;
|
||||||
|
|
||||||
|
ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, ®s, 0,
|
||||||
|
sizeof(regs));
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
putregs(target, ®s);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct user_regset tile_user_regset[] = {
|
||||||
|
[REGSET_GPR] = {
|
||||||
|
.core_note_type = NT_PRSTATUS,
|
||||||
|
.n = ELF_NGREG,
|
||||||
|
.size = sizeof(elf_greg_t),
|
||||||
|
.align = sizeof(elf_greg_t),
|
||||||
|
.get = tile_gpr_get,
|
||||||
|
.set = tile_gpr_set,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct user_regset_view tile_user_regset_view = {
|
||||||
|
.name = CHIP_ARCH_NAME,
|
||||||
|
.e_machine = ELF_ARCH,
|
||||||
|
.ei_osabi = ELF_OSABI,
|
||||||
|
.regsets = tile_user_regset,
|
||||||
|
.n = ARRAY_SIZE(tile_user_regset),
|
||||||
|
};
|
||||||
|
|
||||||
|
const struct user_regset_view *task_user_regset_view(struct task_struct *task)
|
||||||
|
{
|
||||||
|
return &tile_user_regset_view;
|
||||||
|
}
|
||||||
|
|
||||||
long arch_ptrace(struct task_struct *child, long request,
|
long arch_ptrace(struct task_struct *child, long request,
|
||||||
unsigned long addr, unsigned long data)
|
unsigned long addr, unsigned long data)
|
||||||
{
|
{
|
||||||
|
@ -53,14 +150,13 @@ long arch_ptrace(struct task_struct *child, long request,
|
||||||
long ret = -EIO;
|
long ret = -EIO;
|
||||||
char *childreg;
|
char *childreg;
|
||||||
struct pt_regs copyregs;
|
struct pt_regs copyregs;
|
||||||
int ex1_offset;
|
|
||||||
|
|
||||||
switch (request) {
|
switch (request) {
|
||||||
|
|
||||||
case PTRACE_PEEKUSR: /* Read register from pt_regs. */
|
case PTRACE_PEEKUSR: /* Read register from pt_regs. */
|
||||||
if (addr >= PTREGS_SIZE)
|
if (addr >= PTREGS_SIZE)
|
||||||
break;
|
break;
|
||||||
childreg = (char *)task_pt_regs(child) + addr;
|
childreg = getregs(child, ©regs) + addr;
|
||||||
#ifdef CONFIG_COMPAT
|
#ifdef CONFIG_COMPAT
|
||||||
if (is_compat_task()) {
|
if (is_compat_task()) {
|
||||||
if (addr & (sizeof(compat_long_t)-1))
|
if (addr & (sizeof(compat_long_t)-1))
|
||||||
|
@ -79,17 +175,7 @@ long arch_ptrace(struct task_struct *child, long request,
|
||||||
case PTRACE_POKEUSR: /* Write register in pt_regs. */
|
case PTRACE_POKEUSR: /* Write register in pt_regs. */
|
||||||
if (addr >= PTREGS_SIZE)
|
if (addr >= PTREGS_SIZE)
|
||||||
break;
|
break;
|
||||||
childreg = (char *)task_pt_regs(child) + addr;
|
childreg = getregs(child, ©regs) + addr;
|
||||||
|
|
||||||
/* Guard against overwrites of the privilege level. */
|
|
||||||
ex1_offset = PTREGS_OFFSET_EX1;
|
|
||||||
#if defined(CONFIG_COMPAT) && defined(__BIG_ENDIAN)
|
|
||||||
if (is_compat_task()) /* point at low word */
|
|
||||||
ex1_offset += sizeof(compat_long_t);
|
|
||||||
#endif
|
|
||||||
if (addr == ex1_offset)
|
|
||||||
data = PL_ICS_EX1(USER_PL, EX1_ICS(data));
|
|
||||||
|
|
||||||
#ifdef CONFIG_COMPAT
|
#ifdef CONFIG_COMPAT
|
||||||
if (is_compat_task()) {
|
if (is_compat_task()) {
|
||||||
if (addr & (sizeof(compat_long_t)-1))
|
if (addr & (sizeof(compat_long_t)-1))
|
||||||
|
@ -102,24 +188,20 @@ long arch_ptrace(struct task_struct *child, long request,
|
||||||
break;
|
break;
|
||||||
*(long *)childreg = data;
|
*(long *)childreg = data;
|
||||||
}
|
}
|
||||||
|
putregs(child, ©regs);
|
||||||
ret = 0;
|
ret = 0;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PTRACE_GETREGS: /* Get all registers from the child. */
|
case PTRACE_GETREGS: /* Get all registers from the child. */
|
||||||
if (copy_to_user(datap, task_pt_regs(child),
|
ret = copy_regset_to_user(child, &tile_user_regset_view,
|
||||||
sizeof(struct pt_regs)) == 0) {
|
REGSET_GPR, 0,
|
||||||
ret = 0;
|
sizeof(struct pt_regs), datap);
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PTRACE_SETREGS: /* Set all registers in the child. */
|
case PTRACE_SETREGS: /* Set all registers in the child. */
|
||||||
if (copy_from_user(©regs, datap,
|
ret = copy_regset_from_user(child, &tile_user_regset_view,
|
||||||
sizeof(struct pt_regs)) == 0) {
|
REGSET_GPR, 0,
|
||||||
copyregs.ex1 =
|
sizeof(struct pt_regs), datap);
|
||||||
PL_ICS_EX1(USER_PL, EX1_ICS(copyregs.ex1));
|
|
||||||
*task_pt_regs(child) = copyregs;
|
|
||||||
ret = 0;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PTRACE_GETFPREGS: /* Get the child FPU state. */
|
case PTRACE_GETFPREGS: /* Get the child FPU state. */
|
||||||
|
@ -128,12 +210,16 @@ long arch_ptrace(struct task_struct *child, long request,
|
||||||
|
|
||||||
case PTRACE_SETOPTIONS:
|
case PTRACE_SETOPTIONS:
|
||||||
/* Support TILE-specific ptrace options. */
|
/* Support TILE-specific ptrace options. */
|
||||||
child->ptrace &= ~PT_TRACE_MASK_TILE;
|
BUILD_BUG_ON(PTRACE_O_MASK_TILE & PTRACE_O_MASK);
|
||||||
tmp = data & PTRACE_O_MASK_TILE;
|
tmp = data & PTRACE_O_MASK_TILE;
|
||||||
data &= ~PTRACE_O_MASK_TILE;
|
data &= ~PTRACE_O_MASK_TILE;
|
||||||
ret = ptrace_request(child, request, addr, data);
|
ret = ptrace_request(child, request, addr, data);
|
||||||
if (tmp & PTRACE_O_TRACEMIGRATE)
|
if (ret == 0) {
|
||||||
child->ptrace |= PT_TRACE_MIGRATE;
|
unsigned int flags = child->ptrace;
|
||||||
|
flags &= ~(PTRACE_O_MASK_TILE << PT_OPT_FLAG_SHIFT);
|
||||||
|
flags |= (tmp << PT_OPT_FLAG_SHIFT);
|
||||||
|
child->ptrace = flags;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|
Loading…
Reference in New Issue