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 struct membuf to) 219 { 220 struct membuf to_msr = membuf_at(&to, offsetof(struct pt_regs, msr)); 221 int i; 222 223 if (target->thread.regs == NULL) 224 return -EIO; 225 226 if (!FULL_REGS(target->thread.regs)) { 227 /* We have a partial register set. Fill 14-31 with bogus values */ 228 for (i = 14; i < 32; i++) 229 target->thread.regs->gpr[i] = NV_REG_POISON; 230 } 231 232 membuf_write(&to, target->thread.regs, sizeof(struct user_pt_regs)); 233 234 membuf_store(&to_msr, get_user_msr(target)); 235 236 return membuf_zero(&to, ELF_NGREG * sizeof(unsigned long) - 237 sizeof(struct user_pt_regs)); 238 } 239 240 static int gpr_set(struct task_struct *target, const struct user_regset *regset, 241 unsigned int pos, unsigned int count, const void *kbuf, 242 const void __user *ubuf) 243 { 244 unsigned long reg; 245 int ret; 246 247 if (target->thread.regs == NULL) 248 return -EIO; 249 250 CHECK_FULL_REGS(target->thread.regs); 251 252 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, 253 target->thread.regs, 254 0, PT_MSR * sizeof(reg)); 255 256 if (!ret && count > 0) { 257 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, ®, 258 PT_MSR * sizeof(reg), 259 (PT_MSR + 1) * sizeof(reg)); 260 if (!ret) 261 ret = set_user_msr(target, reg); 262 } 263 264 BUILD_BUG_ON(offsetof(struct pt_regs, orig_gpr3) != 265 offsetof(struct pt_regs, msr) + sizeof(long)); 266 267 if (!ret) 268 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, 269 &target->thread.regs->orig_gpr3, 270 PT_ORIG_R3 * sizeof(reg), 271 (PT_MAX_PUT_REG + 1) * sizeof(reg)); 272 273 if (PT_MAX_PUT_REG + 1 < PT_TRAP && !ret) 274 ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf, 275 (PT_MAX_PUT_REG + 1) * sizeof(reg), 276 PT_TRAP * sizeof(reg)); 277 278 if (!ret && count > 0) { 279 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, ®, 280 PT_TRAP * sizeof(reg), 281 (PT_TRAP + 1) * sizeof(reg)); 282 if (!ret) 283 ret = set_user_trap(target, reg); 284 } 285 286 if (!ret) 287 ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf, 288 (PT_TRAP + 1) * sizeof(reg), -1); 289 290 return ret; 291 } 292 293 #ifdef CONFIG_PPC64 294 static int ppr_get(struct task_struct *target, const struct user_regset *regset, 295 struct membuf to) 296 { 297 return membuf_write(&to, &target->thread.regs->ppr, sizeof(u64)); 298 } 299 300 static int ppr_set(struct task_struct *target, const struct user_regset *regset, 301 unsigned int pos, unsigned int count, const void *kbuf, 302 const void __user *ubuf) 303 { 304 return user_regset_copyin(&pos, &count, &kbuf, &ubuf, 305 &target->thread.regs->ppr, 0, sizeof(u64)); 306 } 307 308 static int dscr_get(struct task_struct *target, const struct user_regset *regset, 309 struct membuf to) 310 { 311 return membuf_write(&to, &target->thread.dscr, sizeof(u64)); 312 } 313 static int dscr_set(struct task_struct *target, const struct user_regset *regset, 314 unsigned int pos, unsigned int count, const void *kbuf, 315 const void __user *ubuf) 316 { 317 return user_regset_copyin(&pos, &count, &kbuf, &ubuf, 318 &target->thread.dscr, 0, sizeof(u64)); 319 } 320 #endif 321 #ifdef CONFIG_PPC_BOOK3S_64 322 static int tar_get(struct task_struct *target, const struct user_regset *regset, 323 struct membuf to) 324 { 325 return membuf_write(&to, &target->thread.tar, sizeof(u64)); 326 } 327 static int tar_set(struct task_struct *target, const struct user_regset *regset, 328 unsigned int pos, unsigned int count, const void *kbuf, 329 const void __user *ubuf) 330 { 331 return user_regset_copyin(&pos, &count, &kbuf, &ubuf, 332 &target->thread.tar, 0, sizeof(u64)); 333 } 334 335 static int ebb_active(struct task_struct *target, const struct user_regset *regset) 336 { 337 if (!cpu_has_feature(CPU_FTR_ARCH_207S)) 338 return -ENODEV; 339 340 if (target->thread.used_ebb) 341 return regset->n; 342 343 return 0; 344 } 345 346 static int ebb_get(struct task_struct *target, const struct user_regset *regset, 347 struct membuf to) 348 { 349 /* Build tests */ 350 BUILD_BUG_ON(TSO(ebbrr) + sizeof(unsigned long) != TSO(ebbhr)); 351 BUILD_BUG_ON(TSO(ebbhr) + sizeof(unsigned long) != TSO(bescr)); 352 353 if (!cpu_has_feature(CPU_FTR_ARCH_207S)) 354 return -ENODEV; 355 356 if (!target->thread.used_ebb) 357 return -ENODATA; 358 359 return membuf_write(&to, &target->thread.ebbrr, 3 * sizeof(unsigned long)); 360 } 361 362 static int ebb_set(struct task_struct *target, const struct user_regset *regset, 363 unsigned int pos, unsigned int count, const void *kbuf, 364 const void __user *ubuf) 365 { 366 int ret = 0; 367 368 /* Build tests */ 369 BUILD_BUG_ON(TSO(ebbrr) + sizeof(unsigned long) != TSO(ebbhr)); 370 BUILD_BUG_ON(TSO(ebbhr) + sizeof(unsigned long) != TSO(bescr)); 371 372 if (!cpu_has_feature(CPU_FTR_ARCH_207S)) 373 return -ENODEV; 374 375 if (target->thread.used_ebb) 376 return -ENODATA; 377 378 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &target->thread.ebbrr, 379 0, sizeof(unsigned long)); 380 381 if (!ret) 382 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, 383 &target->thread.ebbhr, sizeof(unsigned long), 384 2 * sizeof(unsigned long)); 385 386 if (!ret) 387 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, 388 &target->thread.bescr, 2 * sizeof(unsigned long), 389 3 * sizeof(unsigned long)); 390 391 return ret; 392 } 393 static int pmu_active(struct task_struct *target, const struct user_regset *regset) 394 { 395 if (!cpu_has_feature(CPU_FTR_ARCH_207S)) 396 return -ENODEV; 397 398 return regset->n; 399 } 400 401 static int pmu_get(struct task_struct *target, const struct user_regset *regset, 402 struct membuf to) 403 { 404 /* Build tests */ 405 BUILD_BUG_ON(TSO(siar) + sizeof(unsigned long) != TSO(sdar)); 406 BUILD_BUG_ON(TSO(sdar) + sizeof(unsigned long) != TSO(sier)); 407 BUILD_BUG_ON(TSO(sier) + sizeof(unsigned long) != TSO(mmcr2)); 408 BUILD_BUG_ON(TSO(mmcr2) + sizeof(unsigned long) != TSO(mmcr0)); 409 410 if (!cpu_has_feature(CPU_FTR_ARCH_207S)) 411 return -ENODEV; 412 413 return membuf_write(&to, &target->thread.siar, 5 * sizeof(unsigned long)); 414 } 415 416 static int pmu_set(struct task_struct *target, const struct user_regset *regset, 417 unsigned int pos, unsigned int count, const void *kbuf, 418 const void __user *ubuf) 419 { 420 int ret = 0; 421 422 /* Build tests */ 423 BUILD_BUG_ON(TSO(siar) + sizeof(unsigned long) != TSO(sdar)); 424 BUILD_BUG_ON(TSO(sdar) + sizeof(unsigned long) != TSO(sier)); 425 BUILD_BUG_ON(TSO(sier) + sizeof(unsigned long) != TSO(mmcr2)); 426 BUILD_BUG_ON(TSO(mmcr2) + sizeof(unsigned long) != TSO(mmcr0)); 427 428 if (!cpu_has_feature(CPU_FTR_ARCH_207S)) 429 return -ENODEV; 430 431 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &target->thread.siar, 432 0, sizeof(unsigned long)); 433 434 if (!ret) 435 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, 436 &target->thread.sdar, sizeof(unsigned long), 437 2 * sizeof(unsigned long)); 438 439 if (!ret) 440 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, 441 &target->thread.sier, 2 * sizeof(unsigned long), 442 3 * sizeof(unsigned long)); 443 444 if (!ret) 445 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, 446 &target->thread.mmcr2, 3 * sizeof(unsigned long), 447 4 * sizeof(unsigned long)); 448 449 if (!ret) 450 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, 451 &target->thread.mmcr0, 4 * sizeof(unsigned long), 452 5 * sizeof(unsigned long)); 453 return ret; 454 } 455 #endif 456 457 #ifdef CONFIG_PPC_MEM_KEYS 458 static int pkey_active(struct task_struct *target, const struct user_regset *regset) 459 { 460 if (!arch_pkeys_enabled()) 461 return -ENODEV; 462 463 return regset->n; 464 } 465 466 static int pkey_get(struct task_struct *target, const struct user_regset *regset, 467 struct membuf to) 468 { 469 BUILD_BUG_ON(TSO(amr) + sizeof(unsigned long) != TSO(iamr)); 470 471 if (!arch_pkeys_enabled()) 472 return -ENODEV; 473 474 membuf_write(&to, &target->thread.amr, 2 * sizeof(unsigned long)); 475 return membuf_store(&to, default_uamor); 476 } 477 478 static int pkey_set(struct task_struct *target, const struct user_regset *regset, 479 unsigned int pos, unsigned int count, const void *kbuf, 480 const void __user *ubuf) 481 { 482 u64 new_amr; 483 int ret; 484 485 if (!arch_pkeys_enabled()) 486 return -ENODEV; 487 488 /* Only the AMR can be set from userspace */ 489 if (pos != 0 || count != sizeof(new_amr)) 490 return -EINVAL; 491 492 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, 493 &new_amr, 0, sizeof(new_amr)); 494 if (ret) 495 return ret; 496 497 /* 498 * UAMOR determines which bits of the AMR can be set from userspace. 499 * UAMOR value 0b11 indicates that the AMR value can be modified 500 * from userspace. If the kernel is using a specific key, we avoid 501 * userspace modifying the AMR value for that key by masking them 502 * via UAMOR 0b00. 503 * 504 * Pick the AMR values for the keys that kernel is using. This 505 * will be indicated by the ~default_uamor bits. 506 */ 507 target->thread.amr = (new_amr & default_uamor) | (target->thread.amr & ~default_uamor); 508 509 return 0; 510 } 511 #endif /* CONFIG_PPC_MEM_KEYS */ 512 513 static const struct user_regset native_regsets[] = { 514 [REGSET_GPR] = { 515 .core_note_type = NT_PRSTATUS, .n = ELF_NGREG, 516 .size = sizeof(long), .align = sizeof(long), 517 .regset_get = gpr_get, .set = gpr_set 518 }, 519 [REGSET_FPR] = { 520 .core_note_type = NT_PRFPREG, .n = ELF_NFPREG, 521 .size = sizeof(double), .align = sizeof(double), 522 .regset_get = fpr_get, .set = fpr_set 523 }, 524 #ifdef CONFIG_ALTIVEC 525 [REGSET_VMX] = { 526 .core_note_type = NT_PPC_VMX, .n = 34, 527 .size = sizeof(vector128), .align = sizeof(vector128), 528 .active = vr_active, .regset_get = vr_get, .set = vr_set 529 }, 530 #endif 531 #ifdef CONFIG_VSX 532 [REGSET_VSX] = { 533 .core_note_type = NT_PPC_VSX, .n = 32, 534 .size = sizeof(double), .align = sizeof(double), 535 .active = vsr_active, .regset_get = vsr_get, .set = vsr_set 536 }, 537 #endif 538 #ifdef CONFIG_SPE 539 [REGSET_SPE] = { 540 .core_note_type = NT_PPC_SPE, .n = 35, 541 .size = sizeof(u32), .align = sizeof(u32), 542 .active = evr_active, .regset_get = evr_get, .set = evr_set 543 }, 544 #endif 545 #ifdef CONFIG_PPC_TRANSACTIONAL_MEM 546 [REGSET_TM_CGPR] = { 547 .core_note_type = NT_PPC_TM_CGPR, .n = ELF_NGREG, 548 .size = sizeof(long), .align = sizeof(long), 549 .active = tm_cgpr_active, .regset_get = tm_cgpr_get, .set = tm_cgpr_set 550 }, 551 [REGSET_TM_CFPR] = { 552 .core_note_type = NT_PPC_TM_CFPR, .n = ELF_NFPREG, 553 .size = sizeof(double), .align = sizeof(double), 554 .active = tm_cfpr_active, .regset_get = tm_cfpr_get, .set = tm_cfpr_set 555 }, 556 [REGSET_TM_CVMX] = { 557 .core_note_type = NT_PPC_TM_CVMX, .n = ELF_NVMX, 558 .size = sizeof(vector128), .align = sizeof(vector128), 559 .active = tm_cvmx_active, .regset_get = tm_cvmx_get, .set = tm_cvmx_set 560 }, 561 [REGSET_TM_CVSX] = { 562 .core_note_type = NT_PPC_TM_CVSX, .n = ELF_NVSX, 563 .size = sizeof(double), .align = sizeof(double), 564 .active = tm_cvsx_active, .regset_get = tm_cvsx_get, .set = tm_cvsx_set 565 }, 566 [REGSET_TM_SPR] = { 567 .core_note_type = NT_PPC_TM_SPR, .n = ELF_NTMSPRREG, 568 .size = sizeof(u64), .align = sizeof(u64), 569 .active = tm_spr_active, .regset_get = tm_spr_get, .set = tm_spr_set 570 }, 571 [REGSET_TM_CTAR] = { 572 .core_note_type = NT_PPC_TM_CTAR, .n = 1, 573 .size = sizeof(u64), .align = sizeof(u64), 574 .active = tm_tar_active, .regset_get = tm_tar_get, .set = tm_tar_set 575 }, 576 [REGSET_TM_CPPR] = { 577 .core_note_type = NT_PPC_TM_CPPR, .n = 1, 578 .size = sizeof(u64), .align = sizeof(u64), 579 .active = tm_ppr_active, .regset_get = tm_ppr_get, .set = tm_ppr_set 580 }, 581 [REGSET_TM_CDSCR] = { 582 .core_note_type = NT_PPC_TM_CDSCR, .n = 1, 583 .size = sizeof(u64), .align = sizeof(u64), 584 .active = tm_dscr_active, .regset_get = tm_dscr_get, .set = tm_dscr_set 585 }, 586 #endif 587 #ifdef CONFIG_PPC64 588 [REGSET_PPR] = { 589 .core_note_type = NT_PPC_PPR, .n = 1, 590 .size = sizeof(u64), .align = sizeof(u64), 591 .regset_get = ppr_get, .set = ppr_set 592 }, 593 [REGSET_DSCR] = { 594 .core_note_type = NT_PPC_DSCR, .n = 1, 595 .size = sizeof(u64), .align = sizeof(u64), 596 .regset_get = dscr_get, .set = dscr_set 597 }, 598 #endif 599 #ifdef CONFIG_PPC_BOOK3S_64 600 [REGSET_TAR] = { 601 .core_note_type = NT_PPC_TAR, .n = 1, 602 .size = sizeof(u64), .align = sizeof(u64), 603 .regset_get = tar_get, .set = tar_set 604 }, 605 [REGSET_EBB] = { 606 .core_note_type = NT_PPC_EBB, .n = ELF_NEBB, 607 .size = sizeof(u64), .align = sizeof(u64), 608 .active = ebb_active, .regset_get = ebb_get, .set = ebb_set 609 }, 610 [REGSET_PMR] = { 611 .core_note_type = NT_PPC_PMU, .n = ELF_NPMU, 612 .size = sizeof(u64), .align = sizeof(u64), 613 .active = pmu_active, .regset_get = pmu_get, .set = pmu_set 614 }, 615 #endif 616 #ifdef CONFIG_PPC_MEM_KEYS 617 [REGSET_PKEY] = { 618 .core_note_type = NT_PPC_PKEY, .n = ELF_NPKEY, 619 .size = sizeof(u64), .align = sizeof(u64), 620 .active = pkey_active, .regset_get = pkey_get, .set = pkey_set 621 }, 622 #endif 623 }; 624 625 const struct user_regset_view user_ppc_native_view = { 626 .name = UTS_MACHINE, .e_machine = ELF_ARCH, .ei_osabi = ELF_OSABI, 627 .regsets = native_regsets, .n = ARRAY_SIZE(native_regsets) 628 }; 629 630 #include <linux/compat.h> 631 632 int gpr32_get_common(struct task_struct *target, 633 const struct user_regset *regset, 634 struct membuf to, unsigned long *regs) 635 { 636 int i; 637 638 for (i = 0; i < PT_MSR; i++) 639 membuf_store(&to, (u32)regs[i]); 640 membuf_store(&to, (u32)get_user_msr(target)); 641 for (i++ ; i < PT_REGS_COUNT; i++) 642 membuf_store(&to, (u32)regs[i]); 643 return membuf_zero(&to, (ELF_NGREG - PT_REGS_COUNT) * sizeof(u32)); 644 } 645 646 int gpr32_set_common(struct task_struct *target, 647 const struct user_regset *regset, 648 unsigned int pos, unsigned int count, 649 const void *kbuf, const void __user *ubuf, 650 unsigned long *regs) 651 { 652 const compat_ulong_t *k = kbuf; 653 const compat_ulong_t __user *u = ubuf; 654 compat_ulong_t reg; 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 if (__get_user(reg, u++)) 665 return -EFAULT; 666 regs[pos++] = reg; 667 } 668 669 670 if (count > 0 && pos == PT_MSR) { 671 if (kbuf) 672 reg = *k++; 673 else if (__get_user(reg, u++)) 674 return -EFAULT; 675 set_user_msr(target, reg); 676 ++pos; 677 --count; 678 } 679 680 if (kbuf) { 681 for (; count > 0 && pos <= PT_MAX_PUT_REG; --count) 682 regs[pos++] = *k++; 683 for (; count > 0 && pos < PT_TRAP; --count, ++pos) 684 ++k; 685 } else { 686 for (; count > 0 && pos <= PT_MAX_PUT_REG; --count) { 687 if (__get_user(reg, u++)) 688 return -EFAULT; 689 regs[pos++] = reg; 690 } 691 for (; count > 0 && pos < PT_TRAP; --count, ++pos) 692 if (__get_user(reg, u++)) 693 return -EFAULT; 694 } 695 696 if (count > 0 && pos == PT_TRAP) { 697 if (kbuf) 698 reg = *k++; 699 else if (__get_user(reg, u++)) 700 return -EFAULT; 701 set_user_trap(target, reg); 702 ++pos; 703 --count; 704 } 705 706 kbuf = k; 707 ubuf = u; 708 pos *= sizeof(reg); 709 count *= sizeof(reg); 710 return user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf, 711 (PT_TRAP + 1) * sizeof(reg), -1); 712 } 713 714 static int gpr32_get(struct task_struct *target, 715 const struct user_regset *regset, 716 struct membuf to) 717 { 718 int i; 719 720 if (target->thread.regs == NULL) 721 return -EIO; 722 723 if (!FULL_REGS(target->thread.regs)) { 724 /* 725 * We have a partial register set. 726 * Fill 14-31 with bogus values. 727 */ 728 for (i = 14; i < 32; i++) 729 target->thread.regs->gpr[i] = NV_REG_POISON; 730 } 731 return gpr32_get_common(target, regset, to, 732 &target->thread.regs->gpr[0]); 733 } 734 735 static int gpr32_set(struct task_struct *target, 736 const struct user_regset *regset, 737 unsigned int pos, unsigned int count, 738 const void *kbuf, const void __user *ubuf) 739 { 740 if (target->thread.regs == NULL) 741 return -EIO; 742 743 CHECK_FULL_REGS(target->thread.regs); 744 return gpr32_set_common(target, regset, pos, count, kbuf, ubuf, 745 &target->thread.regs->gpr[0]); 746 } 747 748 /* 749 * These are the regset flavors matching the CONFIG_PPC32 native set. 750 */ 751 static const struct user_regset compat_regsets[] = { 752 [REGSET_GPR] = { 753 .core_note_type = NT_PRSTATUS, .n = ELF_NGREG, 754 .size = sizeof(compat_long_t), .align = sizeof(compat_long_t), 755 .regset_get = gpr32_get, .set = gpr32_set 756 }, 757 [REGSET_FPR] = { 758 .core_note_type = NT_PRFPREG, .n = ELF_NFPREG, 759 .size = sizeof(double), .align = sizeof(double), 760 .regset_get = fpr_get, .set = fpr_set 761 }, 762 #ifdef CONFIG_ALTIVEC 763 [REGSET_VMX] = { 764 .core_note_type = NT_PPC_VMX, .n = 34, 765 .size = sizeof(vector128), .align = sizeof(vector128), 766 .active = vr_active, .regset_get = vr_get, .set = vr_set 767 }, 768 #endif 769 #ifdef CONFIG_SPE 770 [REGSET_SPE] = { 771 .core_note_type = NT_PPC_SPE, .n = 35, 772 .size = sizeof(u32), .align = sizeof(u32), 773 .active = evr_active, .regset_get = evr_get, .set = evr_set 774 }, 775 #endif 776 #ifdef CONFIG_PPC_TRANSACTIONAL_MEM 777 [REGSET_TM_CGPR] = { 778 .core_note_type = NT_PPC_TM_CGPR, .n = ELF_NGREG, 779 .size = sizeof(long), .align = sizeof(long), 780 .active = tm_cgpr_active, 781 .regset_get = tm_cgpr32_get, .set = tm_cgpr32_set 782 }, 783 [REGSET_TM_CFPR] = { 784 .core_note_type = NT_PPC_TM_CFPR, .n = ELF_NFPREG, 785 .size = sizeof(double), .align = sizeof(double), 786 .active = tm_cfpr_active, .regset_get = tm_cfpr_get, .set = tm_cfpr_set 787 }, 788 [REGSET_TM_CVMX] = { 789 .core_note_type = NT_PPC_TM_CVMX, .n = ELF_NVMX, 790 .size = sizeof(vector128), .align = sizeof(vector128), 791 .active = tm_cvmx_active, .regset_get = tm_cvmx_get, .set = tm_cvmx_set 792 }, 793 [REGSET_TM_CVSX] = { 794 .core_note_type = NT_PPC_TM_CVSX, .n = ELF_NVSX, 795 .size = sizeof(double), .align = sizeof(double), 796 .active = tm_cvsx_active, .regset_get = tm_cvsx_get, .set = tm_cvsx_set 797 }, 798 [REGSET_TM_SPR] = { 799 .core_note_type = NT_PPC_TM_SPR, .n = ELF_NTMSPRREG, 800 .size = sizeof(u64), .align = sizeof(u64), 801 .active = tm_spr_active, .regset_get = tm_spr_get, .set = tm_spr_set 802 }, 803 [REGSET_TM_CTAR] = { 804 .core_note_type = NT_PPC_TM_CTAR, .n = 1, 805 .size = sizeof(u64), .align = sizeof(u64), 806 .active = tm_tar_active, .regset_get = tm_tar_get, .set = tm_tar_set 807 }, 808 [REGSET_TM_CPPR] = { 809 .core_note_type = NT_PPC_TM_CPPR, .n = 1, 810 .size = sizeof(u64), .align = sizeof(u64), 811 .active = tm_ppr_active, .regset_get = tm_ppr_get, .set = tm_ppr_set 812 }, 813 [REGSET_TM_CDSCR] = { 814 .core_note_type = NT_PPC_TM_CDSCR, .n = 1, 815 .size = sizeof(u64), .align = sizeof(u64), 816 .active = tm_dscr_active, .regset_get = tm_dscr_get, .set = tm_dscr_set 817 }, 818 #endif 819 #ifdef CONFIG_PPC64 820 [REGSET_PPR] = { 821 .core_note_type = NT_PPC_PPR, .n = 1, 822 .size = sizeof(u64), .align = sizeof(u64), 823 .regset_get = ppr_get, .set = ppr_set 824 }, 825 [REGSET_DSCR] = { 826 .core_note_type = NT_PPC_DSCR, .n = 1, 827 .size = sizeof(u64), .align = sizeof(u64), 828 .regset_get = dscr_get, .set = dscr_set 829 }, 830 #endif 831 #ifdef CONFIG_PPC_BOOK3S_64 832 [REGSET_TAR] = { 833 .core_note_type = NT_PPC_TAR, .n = 1, 834 .size = sizeof(u64), .align = sizeof(u64), 835 .regset_get = tar_get, .set = tar_set 836 }, 837 [REGSET_EBB] = { 838 .core_note_type = NT_PPC_EBB, .n = ELF_NEBB, 839 .size = sizeof(u64), .align = sizeof(u64), 840 .active = ebb_active, .regset_get = ebb_get, .set = ebb_set 841 }, 842 #endif 843 }; 844 845 static const struct user_regset_view user_ppc_compat_view = { 846 .name = "ppc", .e_machine = EM_PPC, .ei_osabi = ELF_OSABI, 847 .regsets = compat_regsets, .n = ARRAY_SIZE(compat_regsets) 848 }; 849 850 const struct user_regset_view *task_user_regset_view(struct task_struct *task) 851 { 852 if (IS_ENABLED(CONFIG_PPC64) && test_tsk_thread_flag(task, TIF_32BIT)) 853 return &user_ppc_compat_view; 854 return &user_ppc_native_view; 855 } 856