Skip to content

Commit 5b3040a

Browse files
committed
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
2 parents 31564cb + e6cdebd commit 5b3040a

File tree

6 files changed

+126
-34
lines changed

6 files changed

+126
-34
lines changed

arch/tile/include/asm/elf.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,4 +170,6 @@ do { \
170170

171171
#endif /* CONFIG_COMPAT */
172172

173+
#define CORE_DUMP_USE_REGSET
174+
173175
#endif /* _ASM_TILE_ELF_H */

arch/tile/include/asm/ptrace.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,7 @@ typedef unsigned long pt_reg_t;
2424
#include <uapi/asm/ptrace.h>
2525

2626
#define PTRACE_O_MASK_TILE (PTRACE_O_TRACEMIGRATE)
27-
#define PT_TRACE_MIGRATE 0x00080000
28-
#define PT_TRACE_MASK_TILE (PT_TRACE_MIGRATE)
27+
#define PT_TRACE_MIGRATE PT_EVENT_FLAG(PTRACE_EVENT_MIGRATE)
2928

3029
/* Flag bits in pt_regs.flags */
3130
#define PT_FLAGS_DISABLE_IRQ 1 /* on return to kernel, disable irqs */

arch/tile/include/uapi/asm/ptrace.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,8 +81,14 @@ struct pt_regs {
8181
#define PTRACE_SETFPREGS 15
8282

8383
/* Support TILE-specific ptrace options, with events starting at 16. */
84-
#define PTRACE_O_TRACEMIGRATE 0x00010000
8584
#define PTRACE_EVENT_MIGRATE 16
85+
#define PTRACE_O_TRACEMIGRATE (1 << PTRACE_EVENT_MIGRATE)
8686

87+
/*
88+
* Flag bits in pt_regs.flags that are part of the ptrace API.
89+
* We start our numbering higher up to avoid confusion with the
90+
* non-ABI kernel-internal values that use the low 16 bits.
91+
*/
92+
#define PT_FLAGS_COMPAT 0x10000 /* process is an -m32 compat process */
8793

8894
#endif /* _UAPI_ASM_TILE_PTRACE_H */

arch/tile/kernel/pci.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -245,7 +245,7 @@ static void __devinit fixup_read_and_payload_sizes(void)
245245
u16 new_values;
246246

247247
/* Scan for the smallest maximum payload size. */
248-
while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
248+
for_each_pci_dev(dev) {
249249
u32 devcap;
250250
int max_payload;
251251

@@ -260,7 +260,7 @@ static void __devinit fixup_read_and_payload_sizes(void)
260260

261261
/* Now, set the max_payload_size for all devices to that value. */
262262
new_values = (max_read_size << 12) | (smallest_max_payload << 5);
263-
while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL)
263+
for_each_pci_dev(dev)
264264
pcie_capability_clear_and_set_word(dev, PCI_EXP_DEVCTL,
265265
PCI_EXP_DEVCTL_PAYLOAD | PCI_EXP_DEVCTL_READRQ,
266266
new_values);

arch/tile/kernel/pci_gx.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1047,8 +1047,7 @@ int pcibios_enable_device(struct pci_dev *dev, int mask)
10471047
}
10481048

10491049
/* Called for each device after PCI setup is done. */
1050-
static void __init
1051-
pcibios_fixup_final(struct pci_dev *pdev)
1050+
static void pcibios_fixup_final(struct pci_dev *pdev)
10521051
{
10531052
set_dma_ops(&pdev->dev, gx_pci_dma_map_ops);
10541053
set_dma_offset(&pdev->dev, TILE_PCI_MEM_MAP_BASE_OFFSET);

arch/tile/kernel/ptrace.c

Lines changed: 113 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,10 @@
1919
#include <linux/kprobes.h>
2020
#include <linux/compat.h>
2121
#include <linux/uaccess.h>
22+
#include <linux/regset.h>
23+
#include <linux/elf.h>
2224
#include <asm/traps.h>
25+
#include <arch/chip.h>
2326

2427
void user_enable_single_step(struct task_struct *child)
2528
{
@@ -45,6 +48,100 @@ void ptrace_disable(struct task_struct *child)
4548
clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
4649
}
4750

51+
/*
52+
* Get registers from task and ready the result for userspace.
53+
* Note that we localize the API issues to getregs() and putregs() at
54+
* some cost in performance, e.g. we need a full pt_regs copy for
55+
* PEEKUSR, and two copies for POKEUSR. But in general we expect
56+
* GETREGS/PUTREGS to be the API of choice anyway.
57+
*/
58+
static char *getregs(struct task_struct *child, struct pt_regs *uregs)
59+
{
60+
*uregs = *task_pt_regs(child);
61+
62+
/* Set up flags ABI bits. */
63+
uregs->flags = 0;
64+
#ifdef CONFIG_COMPAT
65+
if (task_thread_info(child)->status & TS_COMPAT)
66+
uregs->flags |= PT_FLAGS_COMPAT;
67+
#endif
68+
69+
return (char *)uregs;
70+
}
71+
72+
/* Put registers back to task. */
73+
static void putregs(struct task_struct *child, struct pt_regs *uregs)
74+
{
75+
struct pt_regs *regs = task_pt_regs(child);
76+
77+
/* Don't allow overwriting the kernel-internal flags word. */
78+
uregs->flags = regs->flags;
79+
80+
/* Only allow setting the ICS bit in the ex1 word. */
81+
uregs->ex1 = PL_ICS_EX1(USER_PL, EX1_ICS(uregs->ex1));
82+
83+
*regs = *uregs;
84+
}
85+
86+
enum tile_regset {
87+
REGSET_GPR,
88+
};
89+
90+
static int tile_gpr_get(struct task_struct *target,
91+
const struct user_regset *regset,
92+
unsigned int pos, unsigned int count,
93+
void *kbuf, void __user *ubuf)
94+
{
95+
struct pt_regs regs;
96+
97+
getregs(target, &regs);
98+
99+
return user_regset_copyout(&pos, &count, &kbuf, &ubuf, &regs, 0,
100+
sizeof(regs));
101+
}
102+
103+
static int tile_gpr_set(struct task_struct *target,
104+
const struct user_regset *regset,
105+
unsigned int pos, unsigned int count,
106+
const void *kbuf, const void __user *ubuf)
107+
{
108+
int ret;
109+
struct pt_regs regs;
110+
111+
ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &regs, 0,
112+
sizeof(regs));
113+
if (ret)
114+
return ret;
115+
116+
putregs(target, &regs);
117+
118+
return 0;
119+
}
120+
121+
static const struct user_regset tile_user_regset[] = {
122+
[REGSET_GPR] = {
123+
.core_note_type = NT_PRSTATUS,
124+
.n = ELF_NGREG,
125+
.size = sizeof(elf_greg_t),
126+
.align = sizeof(elf_greg_t),
127+
.get = tile_gpr_get,
128+
.set = tile_gpr_set,
129+
},
130+
};
131+
132+
static const struct user_regset_view tile_user_regset_view = {
133+
.name = CHIP_ARCH_NAME,
134+
.e_machine = ELF_ARCH,
135+
.ei_osabi = ELF_OSABI,
136+
.regsets = tile_user_regset,
137+
.n = ARRAY_SIZE(tile_user_regset),
138+
};
139+
140+
const struct user_regset_view *task_user_regset_view(struct task_struct *task)
141+
{
142+
return &tile_user_regset_view;
143+
}
144+
48145
long arch_ptrace(struct task_struct *child, long request,
49146
unsigned long addr, unsigned long data)
50147
{
@@ -53,14 +150,13 @@ long arch_ptrace(struct task_struct *child, long request,
53150
long ret = -EIO;
54151
char *childreg;
55152
struct pt_regs copyregs;
56-
int ex1_offset;
57153

58154
switch (request) {
59155

60156
case PTRACE_PEEKUSR: /* Read register from pt_regs. */
61157
if (addr >= PTREGS_SIZE)
62158
break;
63-
childreg = (char *)task_pt_regs(child) + addr;
159+
childreg = getregs(child, &copyregs) + addr;
64160
#ifdef CONFIG_COMPAT
65161
if (is_compat_task()) {
66162
if (addr & (sizeof(compat_long_t)-1))
@@ -79,17 +175,7 @@ long arch_ptrace(struct task_struct *child, long request,
79175
case PTRACE_POKEUSR: /* Write register in pt_regs. */
80176
if (addr >= PTREGS_SIZE)
81177
break;
82-
childreg = (char *)task_pt_regs(child) + addr;
83-
84-
/* Guard against overwrites of the privilege level. */
85-
ex1_offset = PTREGS_OFFSET_EX1;
86-
#if defined(CONFIG_COMPAT) && defined(__BIG_ENDIAN)
87-
if (is_compat_task()) /* point at low word */
88-
ex1_offset += sizeof(compat_long_t);
89-
#endif
90-
if (addr == ex1_offset)
91-
data = PL_ICS_EX1(USER_PL, EX1_ICS(data));
92-
178+
childreg = getregs(child, &copyregs) + addr;
93179
#ifdef CONFIG_COMPAT
94180
if (is_compat_task()) {
95181
if (addr & (sizeof(compat_long_t)-1))
@@ -102,24 +188,20 @@ long arch_ptrace(struct task_struct *child, long request,
102188
break;
103189
*(long *)childreg = data;
104190
}
191+
putregs(child, &copyregs);
105192
ret = 0;
106193
break;
107194

108195
case PTRACE_GETREGS: /* Get all registers from the child. */
109-
if (copy_to_user(datap, task_pt_regs(child),
110-
sizeof(struct pt_regs)) == 0) {
111-
ret = 0;
112-
}
196+
ret = copy_regset_to_user(child, &tile_user_regset_view,
197+
REGSET_GPR, 0,
198+
sizeof(struct pt_regs), datap);
113199
break;
114200

115201
case PTRACE_SETREGS: /* Set all registers in the child. */
116-
if (copy_from_user(&copyregs, datap,
117-
sizeof(struct pt_regs)) == 0) {
118-
copyregs.ex1 =
119-
PL_ICS_EX1(USER_PL, EX1_ICS(copyregs.ex1));
120-
*task_pt_regs(child) = copyregs;
121-
ret = 0;
122-
}
202+
ret = copy_regset_from_user(child, &tile_user_regset_view,
203+
REGSET_GPR, 0,
204+
sizeof(struct pt_regs), datap);
123205
break;
124206

125207
case PTRACE_GETFPREGS: /* Get the child FPU state. */
@@ -128,12 +210,16 @@ long arch_ptrace(struct task_struct *child, long request,
128210

129211
case PTRACE_SETOPTIONS:
130212
/* Support TILE-specific ptrace options. */
131-
child->ptrace &= ~PT_TRACE_MASK_TILE;
213+
BUILD_BUG_ON(PTRACE_O_MASK_TILE & PTRACE_O_MASK);
132214
tmp = data & PTRACE_O_MASK_TILE;
133215
data &= ~PTRACE_O_MASK_TILE;
134216
ret = ptrace_request(child, request, addr, data);
135-
if (tmp & PTRACE_O_TRACEMIGRATE)
136-
child->ptrace |= PT_TRACE_MIGRATE;
217+
if (ret == 0) {
218+
unsigned int flags = child->ptrace;
219+
flags &= ~(PTRACE_O_MASK_TILE << PT_OPT_FLAG_SHIFT);
220+
flags |= (tmp << PT_OPT_FLAG_SHIFT);
221+
child->ptrace = flags;
222+
}
137223
break;
138224

139225
default:

0 commit comments

Comments
 (0)