1 // SPDX-License-Identifier: GPL-2.0-or-later 2 3 #include <linux/regset.h> 4 #include <linux/elf.h> 5 #include <linux/nospec.h> 6 #include <linux/pkeys.h> 7 8 #include "ptrace-decl.h" 9 10 struct pt_regs_offset { 11 const char *name; 12 int offset; 13 }; 14 15 #define STR(s) #s /* convert to string */ 16 #define REG_OFFSET_NAME(r) {.name = #r, .offset = offsetof(struct pt_regs, r)} 17 #define GPR_OFFSET_NAME(num) \ 18 {.name = STR(r##num), .offset = offsetof(struct pt_regs, gpr[num])}, \ 19 {.name = STR(gpr##num), .offset = offsetof(struct pt_regs, gpr[num])} 20 #define REG_OFFSET_END {.name = NULL, .offset = 0} 21 22 static const struct pt_regs_offset regoffset_table[] = { 23 GPR_OFFSET_NAME(0), 24 GPR_OFFSET_NAME(1), 25 GPR_OFFSET_NAME(2), 26 GPR_OFFSET_NAME(3), 27 GPR_OFFSET_NAME(4), 28 GPR_OFFSET_NAME(5), 29 GPR_OFFSET_NAME(6), 30 GPR_OFFSET_NAME(7), 31 GPR_OFFSET_NAME(8), 32 GPR_OFFSET_NAME(9), 33 GPR_OFFSET_NAME(10), 34 GPR_OFFSET_NAME(11), 35 GPR_OFFSET_NAME(12), 36 GPR_OFFSET_NAME(13), 37 GPR_OFFSET_NAME(14), 38 GPR_OFFSET_NAME(15), 39 GPR_OFFSET_NAME(16), 40 GPR_OFFSET_NAME(17), 41 GPR_OFFSET_NAME(18), 42 GPR_OFFSET_NAME(19), 43 GPR_OFFSET_NAME(20), 44 GPR_OFFSET_NAME(21), 45 GPR_OFFSET_NAME(22), 46 GPR_OFFSET_NAME(23), 47 GPR_OFFSET_NAME(24), 48 GPR_OFFSET_NAME(25), 49 GPR_OFFSET_NAME(26), 50 GPR_OFFSET_NAME(27), 51 GPR_OFFSET_NAME(28), 52 GPR_OFFSET_NAME(29), 53 GPR_OFFSET_NAME(30), 54 GPR_OFFSET_NAME(31), 55 REG_OFFSET_NAME(nip), 56 REG_OFFSET_NAME(msr), 57 REG_OFFSET_NAME(ctr), 58 REG_OFFSET_NAME(link), 59 REG_OFFSET_NAME(xer), 60 REG_OFFSET_NAME(ccr), 61 #ifdef CONFIG_PPC64 62 REG_OFFSET_NAME(softe), 63 #else 64 REG_OFFSET_NAME(mq), 65 #endif 66 REG_OFFSET_NAME(trap), 67 REG_OFFSET_NAME(dar), 68 REG_OFFSET_NAME(dsisr), 69 REG_OFFSET_END, 70 }; 71 72 /** 73 * regs_query_register_offset() - query register offset from its name 74 * @name: the name of a register 75 * 76 * regs_query_register_offset() returns the offset of a register in struct 77 * pt_regs from its name. If the name is invalid, this returns -EINVAL; 78 */ 79 int regs_query_register_offset(const char *name) 80 { 81 const struct pt_regs_offset *roff; 82 for (roff = regoffset_table; roff->name != NULL; roff++) 83 if (!strcmp(roff->name, name)) 84 return roff->offset; 85 return -EINVAL; 86 } 87 88 /** 89 * regs_query_register_name() - query register name from its offset 90 * @offset: the offset of a register in struct pt_regs. 91 * 92 * regs_query_register_name() returns the name of a register from its 93 * offset in struct pt_regs. If the @offset is invalid, this returns NULL; 94 */ 95 const char *regs_query_register_name(unsigned int offset) 96 { 97 const struct pt_regs_offset *roff; 98 for (roff = regoffset_table; roff->name != NULL; roff++) 99 if (roff->offset == offset) 100 return roff->name; 101 return NULL; 102 } 103 104 /* 105 * does not yet catch signals sent when the child dies. 106 * in exit.c or in signal.c. 107 */ 108 109 static unsigned long get_user_msr(struct task_struct *task) 110 { 111 return task->thread.regs->msr | task->thread.fpexc_mode; 112 } 113 114 static __always_inline int set_user_msr(struct task_struct *task, unsigned long msr) 115 { 116 unsigned long newmsr = (task->thread.regs->msr & ~MSR_DEBUGCHANGE) | 117 (msr & MSR_DEBUGCHANGE); 118 regs_set_return_msr(task->thread.regs, newmsr); 119 return 0; 120 } 121 122 #ifdef CONFIG_PPC64 123 static int get_user_dscr(struct task_struct *task, unsigned long *data) 124 { 125 *data = task->thread.dscr; 126 return 0; 127 } 128 129 static int set_user_dscr(struct task_struct *task, unsigned long dscr) 130 { 131 task->thread.dscr = dscr; 132 task->thread.dscr_inherit = 1; 133 return 0; 134 } 135 #else 136 static int get_user_dscr(struct task_struct *task, unsigned long *data) 137 { 138 return -EIO; 139 } 140 141 static int set_user_dscr(struct task_struct *task, unsigned long dscr) 142 { 143 return -EIO; 144 } 145 #endif 146 147 /* 148 * We prevent mucking around with the reserved area of trap 149 * which are used internally by the kernel. 150 */ 151 static __always_inline int set_user_trap(struct task_struct *task, unsigned long trap) 152 { 153 set_trap(task->thread.regs, trap); 154 return 0; 155 } 156 157 /* 158 * Get contents of register REGNO in task TASK. 159 */ 160 int ptrace_get_reg(struct task_struct *task, int regno, unsigned long *data) 161 { 162 unsigned int regs_max; 163 164 if (task->thread.regs == NULL || !data) 165 return -EIO; 166 167 if (regno == PT_MSR) { 168 *data = get_user_msr(task); 169 return 0; 170 } 171 172 if (regno == PT_DSCR) 173 return get_user_dscr(task, data); 174 175 /* 176 * softe copies paca->irq_soft_mask variable state. Since irq_soft_mask is 177 * no more used as a flag, lets force usr to always see the softe value as 1 178 * which means interrupts are not soft disabled. 179 */ 180 if (IS_ENABLED(CONFIG_PPC64) && regno == PT_SOFTE) { 181 *data = 1; 182 return 0; 183 } 184 185 regs_max = sizeof(struct user_pt_regs) / sizeof(unsigned long); 186 if (regno < regs_max) { 187 regno = array_index_nospec(regno, regs_max); 188 *data = ((unsigned long *)task->thread.regs)[regno]; 189 return 0; 190 } 191 192 return -EIO; 193 } 194 195 /* 196 * Write contents of register REGNO in task TASK. 197 */ 198 int ptrace_put_reg(struct task_struct *task, int regno, unsigned long data) 199 { 200 if (task->thread.regs == NULL) 201 return -EIO; 202 203 if (regno == PT_MSR) 204 return set_user_msr(task, data); 205 if (regno == PT_TRAP) 206 return set_user_trap(task, data); 207 if (regno == PT_DSCR) 208 return set_user_dscr(task, data); 209 210 if (regno <= PT_MAX_PUT_REG) { 211 regno = array_index_nospec(regno, PT_MAX_PUT_REG + 1); 212 ((unsigned long *)task->thread.regs)[regno] = data; 213 return 0; 214 } 215 return -EIO; 216 } 217 218 static int gpr_get(struct task_struct *target, const struct user_regset *regset, 219 struct membuf to) 220 { 221 struct membuf to_msr = membuf_at(&to, offsetof(struct pt_regs, msr)); 222 #ifdef CONFIG_PPC64 223 struct membuf to_softe = membuf_at(&to, offsetof(struct pt_regs, softe)); 224 #endif 225 if (target->thread.regs == NULL) 226 return -EIO; 227 228 membuf_write(&to, target->thread.regs, sizeof(struct user_pt_regs)); 229 230 membuf_store(&to_msr, get_user_msr(target)); 231 #ifdef CONFIG_PPC64 232 membuf_store(&to_softe, 0x1ul); 233 #endif 234 return membuf_zero(&to, ELF_NGREG * sizeof(unsigned long) - 235 sizeof(struct user_pt_regs)); 236 } 237 238 static int gpr_set(struct task_struct *target, const struct user_regset *regset, 239 unsigned int pos, unsigned int count, const void *kbuf, 240 const void __user *ubuf) 241 { 242 unsigned long reg; 243 int ret; 244 245 if (target->thread.regs == NULL) 246 return -EIO; 247 248 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, 249 target->thread.regs, 250 0, PT_MSR * sizeof(reg)); 251 252 if (!ret && count > 0) { 253 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, ®, 254 PT_MSR * sizeof(reg), 255 (PT_MSR + 1) * sizeof(reg)); 256 if (!ret) 257 ret = set_user_msr(target, reg); 258 } 259 260 BUILD_BUG_ON(offsetof(struct pt_regs, orig_gpr3) != 261 offsetof(struct pt_regs, msr) + sizeof(long)); 262 263 if (!ret) 264 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, 265 &target->thread.regs->orig_gpr3, 266 PT_ORIG_R3 * sizeof(reg), 267 (PT_MAX_PUT_REG + 1) * sizeof(reg)); 268 269 if (PT_MAX_PUT_REG + 1 < PT_TRAP && !ret) 270 user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf, 271 (PT_MAX_PUT_REG + 1) * sizeof(reg), 272 PT_TRAP * sizeof(reg)); 273 274 if (!ret && count > 0) { 275 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, ®, 276 PT_TRAP * sizeof(reg), 277 (PT_TRAP + 1) * sizeof(reg)); 278 if (!ret) 279 ret = set_user_trap(target, reg); 280 } 281 282 if (!ret) 283 user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf, 284 (PT_TRAP + 1) * sizeof(reg), -1); 285 286 return ret; 287 } 288 289 #ifdef CONFIG_PPC64 290 static int ppr_get(struct task_struct *target, const struct user_regset *regset, 291 struct membuf to) 292 { 293 return membuf_write(&to, &target->thread.regs->ppr, sizeof(u64)); 294 } 295 296 static int ppr_set(struct task_struct *target, const struct user_regset *regset, 297 unsigned int pos, unsigned int count, const void *kbuf, 298 const void __user *ubuf) 299 { 300 return user_regset_copyin(&pos, &count, &kbuf, &ubuf, 301 &target->thread.regs->ppr, 0, sizeof(u64)); 302 } 303 304 static int dscr_get(struct task_struct *target, const struct user_regset *regset, 305 struct membuf to) 306 { 307 return membuf_write(&to, &target->thread.dscr, sizeof(u64)); 308 } 309 static int dscr_set(struct task_struct *target, const struct user_regset *regset, 310 unsigned int pos, unsigned int count, const void *kbuf, 311 const void __user *ubuf) 312 { 313 return user_regset_copyin(&pos, &count, &kbuf, &ubuf, 314 &target->thread.dscr, 0, sizeof(u64)); 315 } 316 #endif 317 #ifdef CONFIG_PPC_BOOK3S_64 318 static int tar_get(struct task_struct *target, const struct user_regset *regset, 319 struct membuf to) 320 { 321 return membuf_write(&to, &target->thread.tar, sizeof(u64)); 322 } 323 static int tar_set(struct task_struct *target, const struct user_regset *regset, 324 unsigned int pos, unsigned int count, const void *kbuf, 325 const void __user *ubuf) 326 { 327 return user_regset_copyin(&pos, &count, &kbuf, &ubuf, 328 &target->thread.tar, 0, sizeof(u64)); 329 } 330 331 static int ebb_active(struct task_struct *target, const struct user_regset *regset) 332 { 333 if (!cpu_has_feature(CPU_FTR_ARCH_207S)) 334 return -ENODEV; 335 336 if (target->thread.used_ebb) 337 return regset->n; 338 339 return 0; 340 } 341 342 static int ebb_get(struct task_struct *target, const struct user_regset *regset, 343 struct membuf to) 344 { 345 /* Build tests */ 346 BUILD_BUG_ON(TSO(ebbrr) + sizeof(unsigned long) != TSO(ebbhr)); 347 BUILD_BUG_ON(TSO(ebbhr) + sizeof(unsigned long) != TSO(bescr)); 348 349 if (!cpu_has_feature(CPU_FTR_ARCH_207S)) 350 return -ENODEV; 351 352 if (!target->thread.used_ebb) 353 return -ENODATA; 354 355 return membuf_write(&to, &target->thread.ebbrr, 3 * sizeof(unsigned long)); 356 } 357 358 static int ebb_set(struct task_struct *target, const struct user_regset *regset, 359 unsigned int pos, unsigned int count, const void *kbuf, 360 const void __user *ubuf) 361 { 362 int ret = 0; 363 364 /* Build tests */ 365 BUILD_BUG_ON(TSO(ebbrr) + sizeof(unsigned long) != TSO(ebbhr)); 366 BUILD_BUG_ON(TSO(ebbhr) + sizeof(unsigned long) != TSO(bescr)); 367 368 if (!cpu_has_feature(CPU_FTR_ARCH_207S)) 369 return -ENODEV; 370 371 if (target->thread.used_ebb) 372 return -ENODATA; 373 374 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &target->thread.ebbrr, 375 0, sizeof(unsigned long)); 376 377 if (!ret) 378 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, 379 &target->thread.ebbhr, sizeof(unsigned long), 380 2 * sizeof(unsigned long)); 381 382 if (!ret) 383 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, 384 &target->thread.bescr, 2 * sizeof(unsigned long), 385 3 * sizeof(unsigned long)); 386 387 return ret; 388 } 389 static int pmu_active(struct task_struct *target, const struct user_regset *regset) 390 { 391 if (!cpu_has_feature(CPU_FTR_ARCH_207S)) 392 return -ENODEV; 393 394 return regset->n; 395 } 396 397 static int pmu_get(struct task_struct *target, const struct user_regset *regset, 398 struct membuf to) 399 { 400 /* Build tests */ 401 BUILD_BUG_ON(TSO(siar) + sizeof(unsigned long) != TSO(sdar)); 402 BUILD_BUG_ON(TSO(sdar) + sizeof(unsigned long) != TSO(sier)); 403 BUILD_BUG_ON(TSO(sier) + sizeof(unsigned long) != TSO(mmcr2)); 404 BUILD_BUG_ON(TSO(mmcr2) + sizeof(unsigned long) != TSO(mmcr0)); 405 406 if (!cpu_has_feature(CPU_FTR_ARCH_207S)) 407 return -ENODEV; 408 409 return membuf_write(&to, &target->thread.siar, 5 * sizeof(unsigned long)); 410 } 411 412 static int pmu_set(struct task_struct *target, const struct user_regset *regset, 413 unsigned int pos, unsigned int count, const void *kbuf, 414 const void __user *ubuf) 415 { 416 int ret = 0; 417 418 /* Build tests */ 419 BUILD_BUG_ON(TSO(siar) + sizeof(unsigned long) != TSO(sdar)); 420 BUILD_BUG_ON(TSO(sdar) + sizeof(unsigned long) != TSO(sier)); 421 BUILD_BUG_ON(TSO(sier) + sizeof(unsigned long) != TSO(mmcr2)); 422 BUILD_BUG_ON(TSO(mmcr2) + sizeof(unsigned long) != TSO(mmcr0)); 423 424 if (!cpu_has_feature(CPU_FTR_ARCH_207S)) 425 return -ENODEV; 426 427 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &target->thread.siar, 428 0, sizeof(unsigned long)); 429 430 if (!ret) 431 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, 432 &target->thread.sdar, sizeof(unsigned long), 433 2 * sizeof(unsigned long)); 434 435 if (!ret) 436 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, 437 &target->thread.sier, 2 * sizeof(unsigned long), 438 3 * sizeof(unsigned long)); 439 440 if (!ret) 441 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, 442 &target->thread.mmcr2, 3 * sizeof(unsigned long), 443 4 * sizeof(unsigned long)); 444 445 if (!ret) 446 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, 447 &target->thread.mmcr0, 4 * sizeof(unsigned long), 448 5 * sizeof(unsigned long)); 449 return ret; 450 } 451 #endif 452 453 #ifdef CONFIG_PPC_MEM_KEYS 454 static int pkey_active(struct task_struct *target, const struct user_regset *regset) 455 { 456 if (!arch_pkeys_enabled()) 457 return -ENODEV; 458 459 return regset->n; 460 } 461 462 static int pkey_get(struct task_struct *target, const struct user_regset *regset, 463 struct membuf to) 464 { 465 466 if (!arch_pkeys_enabled()) 467 return -ENODEV; 468 469 membuf_store(&to, target->thread.regs->amr); 470 membuf_store(&to, target->thread.regs->iamr); 471 return membuf_store(&to, default_uamor); 472 } 473 474 static int pkey_set(struct task_struct *target, const struct user_regset *regset, 475 unsigned int pos, unsigned int count, const void *kbuf, 476 const void __user *ubuf) 477 { 478 u64 new_amr; 479 int ret; 480 481 if (!arch_pkeys_enabled()) 482 return -ENODEV; 483 484 /* Only the AMR can be set from userspace */ 485 if (pos != 0 || count != sizeof(new_amr)) 486 return -EINVAL; 487 488 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, 489 &new_amr, 0, sizeof(new_amr)); 490 if (ret) 491 return ret; 492 493 /* 494 * UAMOR determines which bits of the AMR can be set from userspace. 495 * UAMOR value 0b11 indicates that the AMR value can be modified 496 * from userspace. If the kernel is using a specific key, we avoid 497 * userspace modifying the AMR value for that key by masking them 498 * via UAMOR 0b00. 499 * 500 * Pick the AMR values for the keys that kernel is using. This 501 * will be indicated by the ~default_uamor bits. 502 */ 503 target->thread.regs->amr = (new_amr & default_uamor) | 504 (target->thread.regs->amr & ~default_uamor); 505 506 return 0; 507 } 508 #endif /* CONFIG_PPC_MEM_KEYS */ 509 510 static const struct user_regset native_regsets[] = { 511 [REGSET_GPR] = { 512 .core_note_type = NT_PRSTATUS, .n = ELF_NGREG, 513 .size = sizeof(long), .align = sizeof(long), 514 .regset_get = gpr_get, .set = gpr_set 515 }, 516 [REGSET_FPR] = { 517 .core_note_type = NT_PRFPREG, .n = ELF_NFPREG, 518 .size = sizeof(double), .align = sizeof(double), 519 .regset_get = fpr_get, .set = fpr_set 520 }, 521 #ifdef CONFIG_ALTIVEC 522 [REGSET_VMX] = { 523 .core_note_type = NT_PPC_VMX, .n = 34, 524 .size = sizeof(vector128), .align = sizeof(vector128), 525 .active = vr_active, .regset_get = vr_get, .set = vr_set 526 }, 527 #endif 528 #ifdef CONFIG_VSX 529 [REGSET_VSX] = { 530 .core_note_type = NT_PPC_VSX, .n = 32, 531 .size = sizeof(double), .align = sizeof(double), 532 .active = vsr_active, .regset_get = vsr_get, .set = vsr_set 533 }, 534 #endif 535 #ifdef CONFIG_SPE 536 [REGSET_SPE] = { 537 .core_note_type = NT_PPC_SPE, .n = 35, 538 .size = sizeof(u32), .align = sizeof(u32), 539 .active = evr_active, .regset_get = evr_get, .set = evr_set 540 }, 541 #endif 542 #ifdef CONFIG_PPC_TRANSACTIONAL_MEM 543 [REGSET_TM_CGPR] = { 544 .core_note_type = NT_PPC_TM_CGPR, .n = ELF_NGREG, 545 .size = sizeof(long), .align = sizeof(long), 546 .active = tm_cgpr_active, .regset_get = tm_cgpr_get, .set = tm_cgpr_set 547 }, 548 [REGSET_TM_CFPR] = { 549 .core_note_type = NT_PPC_TM_CFPR, .n = ELF_NFPREG, 550 .size = sizeof(double), .align = sizeof(double), 551 .active = tm_cfpr_active, .regset_get = tm_cfpr_get, .set = tm_cfpr_set 552 }, 553 [REGSET_TM_CVMX] = { 554 .core_note_type = NT_PPC_TM_CVMX, .n = ELF_NVMX, 555 .size = sizeof(vector128), .align = sizeof(vector128), 556 .active = tm_cvmx_active, .regset_get = tm_cvmx_get, .set = tm_cvmx_set 557 }, 558 [REGSET_TM_CVSX] = { 559 .core_note_type = NT_PPC_TM_CVSX, .n = ELF_NVSX, 560 .size = sizeof(double), .align = sizeof(double), 561 .active = tm_cvsx_active, .regset_get = tm_cvsx_get, .set = tm_cvsx_set 562 }, 563 [REGSET_TM_SPR] = { 564 .core_note_type = NT_PPC_TM_SPR, .n = ELF_NTMSPRREG, 565 .size = sizeof(u64), .align = sizeof(u64), 566 .active = tm_spr_active, .regset_get = tm_spr_get, .set = tm_spr_set 567 }, 568 [REGSET_TM_CTAR] = { 569 .core_note_type = NT_PPC_TM_CTAR, .n = 1, 570 .size = sizeof(u64), .align = sizeof(u64), 571 .active = tm_tar_active, .regset_get = tm_tar_get, .set = tm_tar_set 572 }, 573 [REGSET_TM_CPPR] = { 574 .core_note_type = NT_PPC_TM_CPPR, .n = 1, 575 .size = sizeof(u64), .align = sizeof(u64), 576 .active = tm_ppr_active, .regset_get = tm_ppr_get, .set = tm_ppr_set 577 }, 578 [REGSET_TM_CDSCR] = { 579 .core_note_type = NT_PPC_TM_CDSCR, .n = 1, 580 .size = sizeof(u64), .align = sizeof(u64), 581 .active = tm_dscr_active, .regset_get = tm_dscr_get, .set = tm_dscr_set 582 }, 583 #endif 584 #ifdef CONFIG_PPC64 585 [REGSET_PPR] = { 586 .core_note_type = NT_PPC_PPR, .n = 1, 587 .size = sizeof(u64), .align = sizeof(u64), 588 .regset_get = ppr_get, .set = ppr_set 589 }, 590 [REGSET_DSCR] = { 591 .core_note_type = NT_PPC_DSCR, .n = 1, 592 .size = sizeof(u64), .align = sizeof(u64), 593 .regset_get = dscr_get, .set = dscr_set 594 }, 595 #endif 596 #ifdef CONFIG_PPC_BOOK3S_64 597 [REGSET_TAR] = { 598 .core_note_type = NT_PPC_TAR, .n = 1, 599 .size = sizeof(u64), .align = sizeof(u64), 600 .regset_get = tar_get, .set = tar_set 601 }, 602 [REGSET_EBB] = { 603 .core_note_type = NT_PPC_EBB, .n = ELF_NEBB, 604 .size = sizeof(u64), .align = sizeof(u64), 605 .active = ebb_active, .regset_get = ebb_get, .set = ebb_set 606 }, 607 [REGSET_PMR] = { 608 .core_note_type = NT_PPC_PMU, .n = ELF_NPMU, 609 .size = sizeof(u64), .align = sizeof(u64), 610 .active = pmu_active, .regset_get = pmu_get, .set = pmu_set 611 }, 612 #endif 613 #ifdef CONFIG_PPC_MEM_KEYS 614 [REGSET_PKEY] = { 615 .core_note_type = NT_PPC_PKEY, .n = ELF_NPKEY, 616 .size = sizeof(u64), .align = sizeof(u64), 617 .active = pkey_active, .regset_get = pkey_get, .set = pkey_set 618 }, 619 #endif 620 }; 621 622 const struct user_regset_view user_ppc_native_view = { 623 .name = UTS_MACHINE, .e_machine = ELF_ARCH, .ei_osabi = ELF_OSABI, 624 .regsets = native_regsets, .n = ARRAY_SIZE(native_regsets) 625 }; 626 627 #include <linux/compat.h> 628 629 int gpr32_get_common(struct task_struct *target, 630 const struct user_regset *regset, 631 struct membuf to, unsigned long *regs) 632 { 633 int i; 634 635 for (i = 0; i < PT_MSR; i++) 636 membuf_store(&to, (u32)regs[i]); 637 membuf_store(&to, (u32)get_user_msr(target)); 638 for (i++ ; i < PT_REGS_COUNT; i++) 639 membuf_store(&to, (u32)regs[i]); 640 return membuf_zero(&to, (ELF_NGREG - PT_REGS_COUNT) * sizeof(u32)); 641 } 642 643 int gpr32_set_common(struct task_struct *target, 644 const struct user_regset *regset, 645 unsigned int pos, unsigned int count, 646 const void *kbuf, const void __user *ubuf, 647 unsigned long *regs) 648 { 649 const compat_ulong_t *k = kbuf; 650 const compat_ulong_t __user *u = ubuf; 651 compat_ulong_t reg; 652 653 if (!kbuf && !user_read_access_begin(u, count)) 654 return -EFAULT; 655 656 pos /= sizeof(reg); 657 count /= sizeof(reg); 658 659 if (kbuf) 660 for (; count > 0 && pos < PT_MSR; --count) 661 regs[pos++] = *k++; 662 else 663 for (; count > 0 && pos < PT_MSR; --count) { 664 unsafe_get_user(reg, u++, Efault); 665 regs[pos++] = reg; 666 } 667 668 669 if (count > 0 && pos == PT_MSR) { 670 if (kbuf) 671 reg = *k++; 672 else 673 unsafe_get_user(reg, u++, Efault); 674 set_user_msr(target, reg); 675 ++pos; 676 --count; 677 } 678 679 if (kbuf) { 680 for (; count > 0 && pos <= PT_MAX_PUT_REG; --count) 681 regs[pos++] = *k++; 682 for (; count > 0 && pos < PT_TRAP; --count, ++pos) 683 ++k; 684 } else { 685 for (; count > 0 && pos <= PT_MAX_PUT_REG; --count) { 686 unsafe_get_user(reg, u++, Efault); 687 regs[pos++] = reg; 688 } 689 for (; count > 0 && pos < PT_TRAP; --count, ++pos) 690 unsafe_get_user(reg, u++, Efault); 691 } 692 693 if (count > 0 && pos == PT_TRAP) { 694 if (kbuf) 695 reg = *k++; 696 else 697 unsafe_get_user(reg, u++, Efault); 698 set_user_trap(target, reg); 699 ++pos; 700 --count; 701 } 702 if (!kbuf) 703 user_read_access_end(); 704 705 kbuf = k; 706 ubuf = u; 707 pos *= sizeof(reg); 708 count *= sizeof(reg); 709 user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf, 710 (PT_TRAP + 1) * sizeof(reg), -1); 711 return 0; 712 713 Efault: 714 user_read_access_end(); 715 return -EFAULT; 716 } 717 718 static int gpr32_get(struct task_struct *target, 719 const struct user_regset *regset, 720 struct membuf to) 721 { 722 if (target->thread.regs == NULL) 723 return -EIO; 724 725 return gpr32_get_common(target, regset, to, 726 &target->thread.regs->gpr[0]); 727 } 728 729 static int gpr32_set(struct task_struct *target, 730 const struct user_regset *regset, 731 unsigned int pos, unsigned int count, 732 const void *kbuf, const void __user *ubuf) 733 { 734 if (target->thread.regs == NULL) 735 return -EIO; 736 737 return gpr32_set_common(target, regset, pos, count, kbuf, ubuf, 738 &target->thread.regs->gpr[0]); 739 } 740 741 /* 742 * These are the regset flavors matching the CONFIG_PPC32 native set. 743 */ 744 static const struct user_regset compat_regsets[] = { 745 [REGSET_GPR] = { 746 .core_note_type = NT_PRSTATUS, .n = ELF_NGREG, 747 .size = sizeof(compat_long_t), .align = sizeof(compat_long_t), 748 .regset_get = gpr32_get, .set = gpr32_set 749 }, 750 [REGSET_FPR] = { 751 .core_note_type = NT_PRFPREG, .n = ELF_NFPREG, 752 .size = sizeof(double), .align = sizeof(double), 753 .regset_get = fpr_get, .set = fpr_set 754 }, 755 #ifdef CONFIG_ALTIVEC 756 [REGSET_VMX] = { 757 .core_note_type = NT_PPC_VMX, .n = 34, 758 .size = sizeof(vector128), .align = sizeof(vector128), 759 .active = vr_active, .regset_get = vr_get, .set = vr_set 760 }, 761 #endif 762 #ifdef CONFIG_SPE 763 [REGSET_SPE] = { 764 .core_note_type = NT_PPC_SPE, .n = 35, 765 .size = sizeof(u32), .align = sizeof(u32), 766 .active = evr_active, .regset_get = evr_get, .set = evr_set 767 }, 768 #endif 769 #ifdef CONFIG_PPC_TRANSACTIONAL_MEM 770 [REGSET_TM_CGPR] = { 771 .core_note_type = NT_PPC_TM_CGPR, .n = ELF_NGREG, 772 .size = sizeof(long), .align = sizeof(long), 773 .active = tm_cgpr_active, 774 .regset_get = tm_cgpr32_get, .set = tm_cgpr32_set 775 }, 776 [REGSET_TM_CFPR] = { 777 .core_note_type = NT_PPC_TM_CFPR, .n = ELF_NFPREG, 778 .size = sizeof(double), .align = sizeof(double), 779 .active = tm_cfpr_active, .regset_get = tm_cfpr_get, .set = tm_cfpr_set 780 }, 781 [REGSET_TM_CVMX] = { 782 .core_note_type = NT_PPC_TM_CVMX, .n = ELF_NVMX, 783 .size = sizeof(vector128), .align = sizeof(vector128), 784 .active = tm_cvmx_active, .regset_get = tm_cvmx_get, .set = tm_cvmx_set 785 }, 786 [REGSET_TM_CVSX] = { 787 .core_note_type = NT_PPC_TM_CVSX, .n = ELF_NVSX, 788 .size = sizeof(double), .align = sizeof(double), 789 .active = tm_cvsx_active, .regset_get = tm_cvsx_get, .set = tm_cvsx_set 790 }, 791 [REGSET_TM_SPR] = { 792 .core_note_type = NT_PPC_TM_SPR, .n = ELF_NTMSPRREG, 793 .size = sizeof(u64), .align = sizeof(u64), 794 .active = tm_spr_active, .regset_get = tm_spr_get, .set = tm_spr_set 795 }, 796 [REGSET_TM_CTAR] = { 797 .core_note_type = NT_PPC_TM_CTAR, .n = 1, 798 .size = sizeof(u64), .align = sizeof(u64), 799 .active = tm_tar_active, .regset_get = tm_tar_get, .set = tm_tar_set 800 }, 801 [REGSET_TM_CPPR] = { 802 .core_note_type = NT_PPC_TM_CPPR, .n = 1, 803 .size = sizeof(u64), .align = sizeof(u64), 804 .active = tm_ppr_active, .regset_get = tm_ppr_get, .set = tm_ppr_set 805 }, 806 [REGSET_TM_CDSCR] = { 807 .core_note_type = NT_PPC_TM_CDSCR, .n = 1, 808 .size = sizeof(u64), .align = sizeof(u64), 809 .active = tm_dscr_active, .regset_get = tm_dscr_get, .set = tm_dscr_set 810 }, 811 #endif 812 #ifdef CONFIG_PPC64 813 [REGSET_PPR] = { 814 .core_note_type = NT_PPC_PPR, .n = 1, 815 .size = sizeof(u64), .align = sizeof(u64), 816 .regset_get = ppr_get, .set = ppr_set 817 }, 818 [REGSET_DSCR] = { 819 .core_note_type = NT_PPC_DSCR, .n = 1, 820 .size = sizeof(u64), .align = sizeof(u64), 821 .regset_get = dscr_get, .set = dscr_set 822 }, 823 #endif 824 #ifdef CONFIG_PPC_BOOK3S_64 825 [REGSET_TAR] = { 826 .core_note_type = NT_PPC_TAR, .n = 1, 827 .size = sizeof(u64), .align = sizeof(u64), 828 .regset_get = tar_get, .set = tar_set 829 }, 830 [REGSET_EBB] = { 831 .core_note_type = NT_PPC_EBB, .n = ELF_NEBB, 832 .size = sizeof(u64), .align = sizeof(u64), 833 .active = ebb_active, .regset_get = ebb_get, .set = ebb_set 834 }, 835 #endif 836 }; 837 838 static const struct user_regset_view user_ppc_compat_view = { 839 .name = "ppc", .e_machine = EM_PPC, .ei_osabi = ELF_OSABI, 840 .regsets = compat_regsets, .n = ARRAY_SIZE(compat_regsets) 841 }; 842 843 const struct user_regset_view *task_user_regset_view(struct task_struct *task) 844 { 845 if (IS_ENABLED(CONFIG_COMPAT) && is_tsk_32bit_task(task)) 846 return &user_ppc_compat_view; 847 return &user_ppc_native_view; 848 } 849