diff options
| author | Paul Mackerras <paulus@samba.org> | 2014-09-02 00:35:09 -0400 |
|---|---|---|
| committer | Michael Ellerman <mpe@ellerman.id.au> | 2014-09-25 09:14:52 -0400 |
| commit | c9f6f4ed95d47e3319dedaf8cc31d744ac67fe6f (patch) | |
| tree | 9cd74368175420a8af4197833b4e8b598010856d /arch/powerpc/lib | |
| parent | cf87c3f6b64791ce5d4c7e591c915065d31a162d (diff) | |
powerpc: Implement emulation of string loads and stores
The size field of the op.type word is now the total number of bytes
to be loaded or stored.
Signed-off-by: Paul Mackerras <paulus@samba.org>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Diffstat (limited to 'arch/powerpc/lib')
| -rw-r--r-- | arch/powerpc/lib/sstep.c | 59 |
1 files changed, 49 insertions, 10 deletions
diff --git a/arch/powerpc/lib/sstep.c b/arch/powerpc/lib/sstep.c index 209a506f8517..54651fc2d412 100644 --- a/arch/powerpc/lib/sstep.c +++ b/arch/powerpc/lib/sstep.c | |||
| @@ -1433,11 +1433,24 @@ int __kprobes analyse_instr(struct instruction_op *op, struct pt_regs *regs, | |||
| 1433 | break; | 1433 | break; |
| 1434 | 1434 | ||
| 1435 | #endif | 1435 | #endif |
| 1436 | case 533: /* lswx */ | ||
| 1437 | op->type = MKOP(LOAD_MULTI, 0, regs->xer & 0x7f); | ||
| 1438 | break; | ||
| 1436 | 1439 | ||
| 1437 | case 534: /* lwbrx */ | 1440 | case 534: /* lwbrx */ |
| 1438 | op->type = MKOP(LOAD, BYTEREV, 4); | 1441 | op->type = MKOP(LOAD, BYTEREV, 4); |
| 1439 | break; | 1442 | break; |
| 1440 | 1443 | ||
| 1444 | case 597: /* lswi */ | ||
| 1445 | if (rb == 0) | ||
| 1446 | rb = 32; /* # bytes to load */ | ||
| 1447 | op->type = MKOP(LOAD_MULTI, 0, rb); | ||
| 1448 | op->ea = 0; | ||
| 1449 | if (ra) | ||
| 1450 | op->ea = truncate_if_32bit(regs->msr, | ||
| 1451 | regs->gpr[ra]); | ||
| 1452 | break; | ||
| 1453 | |||
| 1441 | #ifdef CONFIG_PPC_FPU | 1454 | #ifdef CONFIG_PPC_FPU |
| 1442 | case 535: /* lfsx */ | 1455 | case 535: /* lfsx */ |
| 1443 | case 567: /* lfsux */ | 1456 | case 567: /* lfsux */ |
| @@ -1475,11 +1488,25 @@ int __kprobes analyse_instr(struct instruction_op *op, struct pt_regs *regs, | |||
| 1475 | break; | 1488 | break; |
| 1476 | 1489 | ||
| 1477 | #endif | 1490 | #endif |
| 1491 | case 661: /* stswx */ | ||
| 1492 | op->type = MKOP(STORE_MULTI, 0, regs->xer & 0x7f); | ||
| 1493 | break; | ||
| 1494 | |||
| 1478 | case 662: /* stwbrx */ | 1495 | case 662: /* stwbrx */ |
| 1479 | op->type = MKOP(STORE, BYTEREV, 4); | 1496 | op->type = MKOP(STORE, BYTEREV, 4); |
| 1480 | op->val = byterev_4(regs->gpr[rd]); | 1497 | op->val = byterev_4(regs->gpr[rd]); |
| 1481 | break; | 1498 | break; |
| 1482 | 1499 | ||
| 1500 | case 725: | ||
| 1501 | if (rb == 0) | ||
| 1502 | rb = 32; /* # bytes to store */ | ||
| 1503 | op->type = MKOP(STORE_MULTI, 0, rb); | ||
| 1504 | op->ea = 0; | ||
| 1505 | if (ra) | ||
| 1506 | op->ea = truncate_if_32bit(regs->msr, | ||
| 1507 | regs->gpr[ra]); | ||
| 1508 | break; | ||
| 1509 | |||
| 1483 | case 790: /* lhbrx */ | 1510 | case 790: /* lhbrx */ |
| 1484 | op->type = MKOP(LOAD, BYTEREV, 2); | 1511 | op->type = MKOP(LOAD, BYTEREV, 2); |
| 1485 | break; | 1512 | break; |
| @@ -1553,15 +1580,14 @@ int __kprobes analyse_instr(struct instruction_op *op, struct pt_regs *regs, | |||
| 1553 | break; | 1580 | break; |
| 1554 | 1581 | ||
| 1555 | case 46: /* lmw */ | 1582 | case 46: /* lmw */ |
| 1556 | ra = (instr >> 16) & 0x1f; | ||
| 1557 | if (ra >= rd) | 1583 | if (ra >= rd) |
| 1558 | break; /* invalid form, ra in range to load */ | 1584 | break; /* invalid form, ra in range to load */ |
| 1559 | op->type = MKOP(LOAD_MULTI, 0, 4); | 1585 | op->type = MKOP(LOAD_MULTI, 0, 4 * (32 - rd)); |
| 1560 | op->ea = dform_ea(instr, regs); | 1586 | op->ea = dform_ea(instr, regs); |
| 1561 | break; | 1587 | break; |
| 1562 | 1588 | ||
| 1563 | case 47: /* stmw */ | 1589 | case 47: /* stmw */ |
| 1564 | op->type = MKOP(STORE_MULTI, 0, 4); | 1590 | op->type = MKOP(STORE_MULTI, 0, 4 * (32 - rd)); |
| 1565 | op->ea = dform_ea(instr, regs); | 1591 | op->ea = dform_ea(instr, regs); |
| 1566 | break; | 1592 | break; |
| 1567 | 1593 | ||
| @@ -1744,7 +1770,7 @@ int __kprobes emulate_step(struct pt_regs *regs, unsigned int instr) | |||
| 1744 | int r, err, size; | 1770 | int r, err, size; |
| 1745 | unsigned long val; | 1771 | unsigned long val; |
| 1746 | unsigned int cr; | 1772 | unsigned int cr; |
| 1747 | int rd; | 1773 | int i, rd, nb; |
| 1748 | 1774 | ||
| 1749 | r = analyse_instr(&op, regs, instr); | 1775 | r = analyse_instr(&op, regs, instr); |
| 1750 | if (r != 0) | 1776 | if (r != 0) |
| @@ -1866,12 +1892,18 @@ int __kprobes emulate_step(struct pt_regs *regs, unsigned int instr) | |||
| 1866 | if (regs->msr & MSR_LE) | 1892 | if (regs->msr & MSR_LE) |
| 1867 | return 0; | 1893 | return 0; |
| 1868 | rd = op.reg; | 1894 | rd = op.reg; |
| 1869 | do { | 1895 | for (i = 0; i < size; i += 4) { |
| 1870 | err = read_mem(®s->gpr[rd], op.ea, 4, regs); | 1896 | nb = size - i; |
| 1897 | if (nb > 4) | ||
| 1898 | nb = 4; | ||
| 1899 | err = read_mem(®s->gpr[rd], op.ea, nb, regs); | ||
| 1871 | if (err) | 1900 | if (err) |
| 1872 | return 0; | 1901 | return 0; |
| 1902 | if (nb < 4) /* left-justify last bytes */ | ||
| 1903 | regs->gpr[rd] <<= 32 - 8 * nb; | ||
| 1873 | op.ea += 4; | 1904 | op.ea += 4; |
| 1874 | } while (++rd < 32); | 1905 | ++rd; |
| 1906 | } | ||
| 1875 | goto instr_done; | 1907 | goto instr_done; |
| 1876 | 1908 | ||
| 1877 | case STORE: | 1909 | case STORE: |
| @@ -1914,12 +1946,19 @@ int __kprobes emulate_step(struct pt_regs *regs, unsigned int instr) | |||
| 1914 | if (regs->msr & MSR_LE) | 1946 | if (regs->msr & MSR_LE) |
| 1915 | return 0; | 1947 | return 0; |
| 1916 | rd = op.reg; | 1948 | rd = op.reg; |
| 1917 | do { | 1949 | for (i = 0; i < size; i += 4) { |
| 1918 | err = write_mem(regs->gpr[rd], op.ea, 4, regs); | 1950 | val = regs->gpr[rd]; |
| 1951 | nb = size - i; | ||
| 1952 | if (nb > 4) | ||
| 1953 | nb = 4; | ||
| 1954 | else | ||
| 1955 | val >>= 32 - 8 * nb; | ||
| 1956 | err = write_mem(val, op.ea, nb, regs); | ||
| 1919 | if (err) | 1957 | if (err) |
| 1920 | return 0; | 1958 | return 0; |
| 1921 | op.ea += 4; | 1959 | op.ea += 4; |
| 1922 | } while (++rd < 32); | 1960 | ++rd; |
| 1961 | } | ||
| 1923 | goto instr_done; | 1962 | goto instr_done; |
| 1924 | 1963 | ||
| 1925 | case MFMSR: | 1964 | case MFMSR: |
