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 task->thread.regs->trap = trap & 0xfff0; 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 BUILD_BUG_ON(TSO(amr) + sizeof(unsigned long) != TSO(iamr)); 492 BUILD_BUG_ON(TSO(iamr) + sizeof(unsigned long) != TSO(uamor)); 493 494 if (!arch_pkeys_enabled()) 495 return -ENODEV; 496 497 return user_regset_copyout(&pos, &count, &kbuf, &ubuf, &target->thread.amr, 498 0, ELF_NPKEY * sizeof(unsigned long)); 499 } 500 501 static int pkey_set(struct task_struct *target, const struct user_regset *regset, 502 unsigned int pos, unsigned int count, const void *kbuf, 503 const void __user *ubuf) 504 { 505 u64 new_amr; 506 int ret; 507 508 if (!arch_pkeys_enabled()) 509 return -ENODEV; 510 511 /* Only the AMR can be set from userspace */ 512 if (pos != 0 || count != sizeof(new_amr)) 513 return -EINVAL; 514 515 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, 516 &new_amr, 0, sizeof(new_amr)); 517 if (ret) 518 return ret; 519 520 /* UAMOR determines which bits of the AMR can be set from userspace. */ 521 target->thread.amr = (new_amr & target->thread.uamor) | 522 (target->thread.amr & ~target->thread.uamor); 523 524 return 0; 525 } 526 #endif /* CONFIG_PPC_MEM_KEYS */ 527 528 static const struct user_regset native_regsets[] = { 529 [REGSET_GPR] = { 530 .core_note_type = NT_PRSTATUS, .n = ELF_NGREG, 531 .size = sizeof(long), .align = sizeof(long), 532 .get = gpr_get, .set = gpr_set 533 }, 534 [REGSET_FPR] = { 535 .core_note_type = NT_PRFPREG, .n = ELF_NFPREG, 536 .size = sizeof(double), .align = sizeof(double), 537 .get = fpr_get, .set = fpr_set 538 }, 539 #ifdef CONFIG_ALTIVEC 540 [REGSET_VMX] = { 541 .core_note_type = NT_PPC_VMX, .n = 34, 542 .size = sizeof(vector128), .align = sizeof(vector128), 543 .active = vr_active, .get = vr_get, .set = vr_set 544 }, 545 #endif 546 #ifdef CONFIG_VSX 547 [REGSET_VSX] = { 548 .core_note_type = NT_PPC_VSX, .n = 32, 549 .size = sizeof(double), .align = sizeof(double), 550 .active = vsr_active, .get = vsr_get, .set = vsr_set 551 }, 552 #endif 553 #ifdef CONFIG_SPE 554 [REGSET_SPE] = { 555 .core_note_type = NT_PPC_SPE, .n = 35, 556 .size = sizeof(u32), .align = sizeof(u32), 557 .active = evr_active, .get = evr_get, .set = evr_set 558 }, 559 #endif 560 #ifdef CONFIG_PPC_TRANSACTIONAL_MEM 561 [REGSET_TM_CGPR] = { 562 .core_note_type = NT_PPC_TM_CGPR, .n = ELF_NGREG, 563 .size = sizeof(long), .align = sizeof(long), 564 .active = tm_cgpr_active, .get = tm_cgpr_get, .set = tm_cgpr_set 565 }, 566 [REGSET_TM_CFPR] = { 567 .core_note_type = NT_PPC_TM_CFPR, .n = ELF_NFPREG, 568 .size = sizeof(double), .align = sizeof(double), 569 .active = tm_cfpr_active, .get = tm_cfpr_get, .set = tm_cfpr_set 570 }, 571 [REGSET_TM_CVMX] = { 572 .core_note_type = NT_PPC_TM_CVMX, .n = ELF_NVMX, 573 .size = sizeof(vector128), .align = sizeof(vector128), 574 .active = tm_cvmx_active, .get = tm_cvmx_get, .set = tm_cvmx_set 575 }, 576 [REGSET_TM_CVSX] = { 577 .core_note_type = NT_PPC_TM_CVSX, .n = ELF_NVSX, 578 .size = sizeof(double), .align = sizeof(double), 579 .active = tm_cvsx_active, .get = tm_cvsx_get, .set = tm_cvsx_set 580 }, 581 [REGSET_TM_SPR] = { 582 .core_note_type = NT_PPC_TM_SPR, .n = ELF_NTMSPRREG, 583 .size = sizeof(u64), .align = sizeof(u64), 584 .active = tm_spr_active, .get = tm_spr_get, .set = tm_spr_set 585 }, 586 [REGSET_TM_CTAR] = { 587 .core_note_type = NT_PPC_TM_CTAR, .n = 1, 588 .size = sizeof(u64), .align = sizeof(u64), 589 .active = tm_tar_active, .get = tm_tar_get, .set = tm_tar_set 590 }, 591 [REGSET_TM_CPPR] = { 592 .core_note_type = NT_PPC_TM_CPPR, .n = 1, 593 .size = sizeof(u64), .align = sizeof(u64), 594 .active = tm_ppr_active, .get = tm_ppr_get, .set = tm_ppr_set 595 }, 596 [REGSET_TM_CDSCR] = { 597 .core_note_type = NT_PPC_TM_CDSCR, .n = 1, 598 .size = sizeof(u64), .align = sizeof(u64), 599 .active = tm_dscr_active, .get = tm_dscr_get, .set = tm_dscr_set 600 }, 601 #endif 602 #ifdef CONFIG_PPC64 603 [REGSET_PPR] = { 604 .core_note_type = NT_PPC_PPR, .n = 1, 605 .size = sizeof(u64), .align = sizeof(u64), 606 .get = ppr_get, .set = ppr_set 607 }, 608 [REGSET_DSCR] = { 609 .core_note_type = NT_PPC_DSCR, .n = 1, 610 .size = sizeof(u64), .align = sizeof(u64), 611 .get = dscr_get, .set = dscr_set 612 }, 613 #endif 614 #ifdef CONFIG_PPC_BOOK3S_64 615 [REGSET_TAR] = { 616 .core_note_type = NT_PPC_TAR, .n = 1, 617 .size = sizeof(u64), .align = sizeof(u64), 618 .get = tar_get, .set = tar_set 619 }, 620 [REGSET_EBB] = { 621 .core_note_type = NT_PPC_EBB, .n = ELF_NEBB, 622 .size = sizeof(u64), .align = sizeof(u64), 623 .active = ebb_active, .get = ebb_get, .set = ebb_set 624 }, 625 [REGSET_PMR] = { 626 .core_note_type = NT_PPC_PMU, .n = ELF_NPMU, 627 .size = sizeof(u64), .align = sizeof(u64), 628 .active = pmu_active, .get = pmu_get, .set = pmu_set 629 }, 630 #endif 631 #ifdef CONFIG_PPC_MEM_KEYS 632 [REGSET_PKEY] = { 633 .core_note_type = NT_PPC_PKEY, .n = ELF_NPKEY, 634 .size = sizeof(u64), .align = sizeof(u64), 635 .active = pkey_active, .get = pkey_get, .set = pkey_set 636 }, 637 #endif 638 }; 639 640 const struct user_regset_view user_ppc_native_view = { 641 .name = UTS_MACHINE, .e_machine = ELF_ARCH, .ei_osabi = ELF_OSABI, 642 .regsets = native_regsets, .n = ARRAY_SIZE(native_regsets) 643 }; 644 645 #include <linux/compat.h> 646 647 int gpr32_get_common(struct task_struct *target, 648 const struct user_regset *regset, 649 unsigned int pos, unsigned int count, 650 void *kbuf, void __user *ubuf, 651 unsigned long *regs) 652 { 653 compat_ulong_t *k = kbuf; 654 compat_ulong_t __user *u = ubuf; 655 compat_ulong_t reg; 656 657 pos /= sizeof(reg); 658 count /= sizeof(reg); 659 660 if (kbuf) 661 for (; count > 0 && pos < PT_MSR; --count) 662 *k++ = regs[pos++]; 663 else 664 for (; count > 0 && pos < PT_MSR; --count) 665 if (__put_user((compat_ulong_t)regs[pos++], u++)) 666 return -EFAULT; 667 668 if (count > 0 && pos == PT_MSR) { 669 reg = get_user_msr(target); 670 if (kbuf) 671 *k++ = reg; 672 else if (__put_user(reg, u++)) 673 return -EFAULT; 674 ++pos; 675 --count; 676 } 677 678 if (kbuf) 679 for (; count > 0 && pos < PT_REGS_COUNT; --count) 680 *k++ = regs[pos++]; 681 else 682 for (; count > 0 && pos < PT_REGS_COUNT; --count) 683 if (__put_user((compat_ulong_t)regs[pos++], u++)) 684 return -EFAULT; 685 686 kbuf = k; 687 ubuf = u; 688 pos *= sizeof(reg); 689 count *= sizeof(reg); 690 return user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf, 691 PT_REGS_COUNT * sizeof(reg), -1); 692 } 693 694 int gpr32_set_common(struct task_struct *target, 695 const struct user_regset *regset, 696 unsigned int pos, unsigned int count, 697 const void *kbuf, const void __user *ubuf, 698 unsigned long *regs) 699 { 700 const compat_ulong_t *k = kbuf; 701 const compat_ulong_t __user *u = ubuf; 702 compat_ulong_t reg; 703 704 pos /= sizeof(reg); 705 count /= sizeof(reg); 706 707 if (kbuf) 708 for (; count > 0 && pos < PT_MSR; --count) 709 regs[pos++] = *k++; 710 else 711 for (; count > 0 && pos < PT_MSR; --count) { 712 if (__get_user(reg, u++)) 713 return -EFAULT; 714 regs[pos++] = reg; 715 } 716 717 718 if (count > 0 && pos == PT_MSR) { 719 if (kbuf) 720 reg = *k++; 721 else if (__get_user(reg, u++)) 722 return -EFAULT; 723 set_user_msr(target, reg); 724 ++pos; 725 --count; 726 } 727 728 if (kbuf) { 729 for (; count > 0 && pos <= PT_MAX_PUT_REG; --count) 730 regs[pos++] = *k++; 731 for (; count > 0 && pos < PT_TRAP; --count, ++pos) 732 ++k; 733 } else { 734 for (; count > 0 && pos <= PT_MAX_PUT_REG; --count) { 735 if (__get_user(reg, u++)) 736 return -EFAULT; 737 regs[pos++] = reg; 738 } 739 for (; count > 0 && pos < PT_TRAP; --count, ++pos) 740 if (__get_user(reg, u++)) 741 return -EFAULT; 742 } 743 744 if (count > 0 && pos == PT_TRAP) { 745 if (kbuf) 746 reg = *k++; 747 else if (__get_user(reg, u++)) 748 return -EFAULT; 749 set_user_trap(target, reg); 750 ++pos; 751 --count; 752 } 753 754 kbuf = k; 755 ubuf = u; 756 pos *= sizeof(reg); 757 count *= sizeof(reg); 758 return user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf, 759 (PT_TRAP + 1) * sizeof(reg), -1); 760 } 761 762 static int gpr32_get(struct task_struct *target, 763 const struct user_regset *regset, 764 unsigned int pos, unsigned int count, 765 void *kbuf, void __user *ubuf) 766 { 767 int i; 768 769 if (target->thread.regs == NULL) 770 return -EIO; 771 772 if (!FULL_REGS(target->thread.regs)) { 773 /* 774 * We have a partial register set. 775 * Fill 14-31 with bogus values. 776 */ 777 for (i = 14; i < 32; i++) 778 target->thread.regs->gpr[i] = NV_REG_POISON; 779 } 780 return gpr32_get_common(target, regset, pos, count, kbuf, ubuf, 781 &target->thread.regs->gpr[0]); 782 } 783 784 static int gpr32_set(struct task_struct *target, 785 const struct user_regset *regset, 786 unsigned int pos, unsigned int count, 787 const void *kbuf, const void __user *ubuf) 788 { 789 if (target->thread.regs == NULL) 790 return -EIO; 791 792 CHECK_FULL_REGS(target->thread.regs); 793 return gpr32_set_common(target, regset, pos, count, kbuf, ubuf, 794 &target->thread.regs->gpr[0]); 795 } 796 797 /* 798 * These are the regset flavors matching the CONFIG_PPC32 native set. 799 */ 800 static const struct user_regset compat_regsets[] = { 801 [REGSET_GPR] = { 802 .core_note_type = NT_PRSTATUS, .n = ELF_NGREG, 803 .size = sizeof(compat_long_t), .align = sizeof(compat_long_t), 804 .get = gpr32_get, .set = gpr32_set 805 }, 806 [REGSET_FPR] = { 807 .core_note_type = NT_PRFPREG, .n = ELF_NFPREG, 808 .size = sizeof(double), .align = sizeof(double), 809 .get = fpr_get, .set = fpr_set 810 }, 811 #ifdef CONFIG_ALTIVEC 812 [REGSET_VMX] = { 813 .core_note_type = NT_PPC_VMX, .n = 34, 814 .size = sizeof(vector128), .align = sizeof(vector128), 815 .active = vr_active, .get = vr_get, .set = vr_set 816 }, 817 #endif 818 #ifdef CONFIG_SPE 819 [REGSET_SPE] = { 820 .core_note_type = NT_PPC_SPE, .n = 35, 821 .size = sizeof(u32), .align = sizeof(u32), 822 .active = evr_active, .get = evr_get, .set = evr_set 823 }, 824 #endif 825 #ifdef CONFIG_PPC_TRANSACTIONAL_MEM 826 [REGSET_TM_CGPR] = { 827 .core_note_type = NT_PPC_TM_CGPR, .n = ELF_NGREG, 828 .size = sizeof(long), .align = sizeof(long), 829 .active = tm_cgpr_active, 830 .get = tm_cgpr32_get, .set = tm_cgpr32_set 831 }, 832 [REGSET_TM_CFPR] = { 833 .core_note_type = NT_PPC_TM_CFPR, .n = ELF_NFPREG, 834 .size = sizeof(double), .align = sizeof(double), 835 .active = tm_cfpr_active, .get = tm_cfpr_get, .set = tm_cfpr_set 836 }, 837 [REGSET_TM_CVMX] = { 838 .core_note_type = NT_PPC_TM_CVMX, .n = ELF_NVMX, 839 .size = sizeof(vector128), .align = sizeof(vector128), 840 .active = tm_cvmx_active, .get = tm_cvmx_get, .set = tm_cvmx_set 841 }, 842 [REGSET_TM_CVSX] = { 843 .core_note_type = NT_PPC_TM_CVSX, .n = ELF_NVSX, 844 .size = sizeof(double), .align = sizeof(double), 845 .active = tm_cvsx_active, .get = tm_cvsx_get, .set = tm_cvsx_set 846 }, 847 [REGSET_TM_SPR] = { 848 .core_note_type = NT_PPC_TM_SPR, .n = ELF_NTMSPRREG, 849 .size = sizeof(u64), .align = sizeof(u64), 850 .active = tm_spr_active, .get = tm_spr_get, .set = tm_spr_set 851 }, 852 [REGSET_TM_CTAR] = { 853 .core_note_type = NT_PPC_TM_CTAR, .n = 1, 854 .size = sizeof(u64), .align = sizeof(u64), 855 .active = tm_tar_active, .get = tm_tar_get, .set = tm_tar_set 856 }, 857 [REGSET_TM_CPPR] = { 858 .core_note_type = NT_PPC_TM_CPPR, .n = 1, 859 .size = sizeof(u64), .align = sizeof(u64), 860 .active = tm_ppr_active, .get = tm_ppr_get, .set = tm_ppr_set 861 }, 862 [REGSET_TM_CDSCR] = { 863 .core_note_type = NT_PPC_TM_CDSCR, .n = 1, 864 .size = sizeof(u64), .align = sizeof(u64), 865 .active = tm_dscr_active, .get = tm_dscr_get, .set = tm_dscr_set 866 }, 867 #endif 868 #ifdef CONFIG_PPC64 869 [REGSET_PPR] = { 870 .core_note_type = NT_PPC_PPR, .n = 1, 871 .size = sizeof(u64), .align = sizeof(u64), 872 .get = ppr_get, .set = ppr_set 873 }, 874 [REGSET_DSCR] = { 875 .core_note_type = NT_PPC_DSCR, .n = 1, 876 .size = sizeof(u64), .align = sizeof(u64), 877 .get = dscr_get, .set = dscr_set 878 }, 879 #endif 880 #ifdef CONFIG_PPC_BOOK3S_64 881 [REGSET_TAR] = { 882 .core_note_type = NT_PPC_TAR, .n = 1, 883 .size = sizeof(u64), .align = sizeof(u64), 884 .get = tar_get, .set = tar_set 885 }, 886 [REGSET_EBB] = { 887 .core_note_type = NT_PPC_EBB, .n = ELF_NEBB, 888 .size = sizeof(u64), .align = sizeof(u64), 889 .active = ebb_active, .get = ebb_get, .set = ebb_set 890 }, 891 #endif 892 }; 893 894 static const struct user_regset_view user_ppc_compat_view = { 895 .name = "ppc", .e_machine = EM_PPC, .ei_osabi = ELF_OSABI, 896 .regsets = compat_regsets, .n = ARRAY_SIZE(compat_regsets) 897 }; 898 899 const struct user_regset_view *task_user_regset_view(struct task_struct *task) 900 { 901 if (IS_ENABLED(CONFIG_PPC64) && test_tsk_thread_flag(task, TIF_32BIT)) 902 return &user_ppc_compat_view; 903 return &user_ppc_native_view; 904 } 905