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