qemu with hax to log dma reads & writes jcs.org/2018/11/12/vfio

tcg: Restart TB generation after out-of-line ldst overflow

This is part c of relocation overflow handling.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>

+75 -44
+10 -6
tcg/aarch64/tcg-target.inc.c
··· 1395 1395 tcg_out_insn(s, 3406, ADR, rd, offset); 1396 1396 } 1397 1397 1398 - static void tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *lb) 1398 + static bool tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *lb) 1399 1399 { 1400 1400 TCGMemOpIdx oi = lb->oi; 1401 1401 TCGMemOp opc = get_memop(oi); 1402 1402 TCGMemOp size = opc & MO_SIZE; 1403 1403 1404 - bool ok = reloc_pc19(lb->label_ptr[0], s->code_ptr); 1405 - tcg_debug_assert(ok); 1404 + if (!reloc_pc19(lb->label_ptr[0], s->code_ptr)) { 1405 + return false; 1406 + } 1406 1407 1407 1408 tcg_out_mov(s, TCG_TYPE_PTR, TCG_REG_X0, TCG_AREG0); 1408 1409 tcg_out_mov(s, TARGET_LONG_BITS == 64, TCG_REG_X1, lb->addrlo_reg); ··· 1416 1417 } 1417 1418 1418 1419 tcg_out_goto(s, lb->raddr); 1420 + return true; 1419 1421 } 1420 1422 1421 - static void tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *lb) 1423 + static bool tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *lb) 1422 1424 { 1423 1425 TCGMemOpIdx oi = lb->oi; 1424 1426 TCGMemOp opc = get_memop(oi); 1425 1427 TCGMemOp size = opc & MO_SIZE; 1426 1428 1427 - bool ok = reloc_pc19(lb->label_ptr[0], s->code_ptr); 1428 - tcg_debug_assert(ok); 1429 + if (!reloc_pc19(lb->label_ptr[0], s->code_ptr)) { 1430 + return false; 1431 + } 1429 1432 1430 1433 tcg_out_mov(s, TCG_TYPE_PTR, TCG_REG_X0, TCG_AREG0); 1431 1434 tcg_out_mov(s, TARGET_LONG_BITS == 64, TCG_REG_X1, lb->addrlo_reg); ··· 1434 1437 tcg_out_adr(s, TCG_REG_X4, lb->raddr); 1435 1438 tcg_out_call(s, qemu_st_helpers[opc & (MO_BSWAP | MO_SIZE)]); 1436 1439 tcg_out_goto(s, lb->raddr); 1440 + return true; 1437 1441 } 1438 1442 1439 1443 static void add_qemu_ldst_label(TCGContext *s, bool is_ld, TCGMemOpIdx oi,
+10 -6
tcg/arm/tcg-target.inc.c
··· 1372 1372 label->label_ptr[0] = label_ptr; 1373 1373 } 1374 1374 1375 - static void tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *lb) 1375 + static bool tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *lb) 1376 1376 { 1377 1377 TCGReg argreg, datalo, datahi; 1378 1378 TCGMemOpIdx oi = lb->oi; 1379 1379 TCGMemOp opc = get_memop(oi); 1380 1380 void *func; 1381 1381 1382 - bool ok = reloc_pc24(lb->label_ptr[0], s->code_ptr); 1383 - tcg_debug_assert(ok); 1382 + if (!reloc_pc24(lb->label_ptr[0], s->code_ptr)) { 1383 + return false; 1384 + } 1384 1385 1385 1386 argreg = tcg_out_arg_reg32(s, TCG_REG_R0, TCG_AREG0); 1386 1387 if (TARGET_LONG_BITS == 64) { ··· 1432 1433 } 1433 1434 1434 1435 tcg_out_goto(s, COND_AL, lb->raddr); 1436 + return true; 1435 1437 } 1436 1438 1437 - static void tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *lb) 1439 + static bool tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *lb) 1438 1440 { 1439 1441 TCGReg argreg, datalo, datahi; 1440 1442 TCGMemOpIdx oi = lb->oi; 1441 1443 TCGMemOp opc = get_memop(oi); 1442 1444 1443 - bool ok = reloc_pc24(lb->label_ptr[0], s->code_ptr); 1444 - tcg_debug_assert(ok); 1445 + if (!reloc_pc24(lb->label_ptr[0], s->code_ptr)) { 1446 + return false; 1447 + } 1445 1448 1446 1449 argreg = TCG_REG_R0; 1447 1450 argreg = tcg_out_arg_reg32(s, argreg, TCG_AREG0); ··· 1474 1477 1475 1478 /* Tail-call to the helper, which will return to the fast path. */ 1476 1479 tcg_out_goto(s, COND_AL, qemu_st_helpers[opc & (MO_BSWAP | MO_SIZE)]); 1480 + return true; 1477 1481 } 1478 1482 #endif /* SOFTMMU */ 1479 1483
+4 -2
tcg/i386/tcg-target.inc.c
··· 1730 1730 /* 1731 1731 * Generate code for the slow path for a load at the end of block 1732 1732 */ 1733 - static void tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *l) 1733 + static bool tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *l) 1734 1734 { 1735 1735 TCGMemOpIdx oi = l->oi; 1736 1736 TCGMemOp opc = get_memop(oi); ··· 1809 1809 1810 1810 /* Jump to the code corresponding to next IR of qemu_st */ 1811 1811 tcg_out_jmp(s, l->raddr); 1812 + return true; 1812 1813 } 1813 1814 1814 1815 /* 1815 1816 * Generate code for the slow path for a store at the end of block 1816 1817 */ 1817 - static void tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *l) 1818 + static bool tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *l) 1818 1819 { 1819 1820 TCGMemOpIdx oi = l->oi; 1820 1821 TCGMemOp opc = get_memop(oi); ··· 1877 1878 /* "Tail call" to the helper, with the return address back inline. */ 1878 1879 tcg_out_push(s, retaddr); 1879 1880 tcg_out_jmp(s, qemu_st_helpers[opc & (MO_BSWAP | MO_SIZE)]); 1881 + return true; 1880 1882 } 1881 1883 #elif TCG_TARGET_REG_BITS == 32 1882 1884 # define x86_guest_base_seg 0
+4 -2
tcg/mips/tcg-target.inc.c
··· 1338 1338 } 1339 1339 } 1340 1340 1341 - static void tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *l) 1341 + static bool tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *l) 1342 1342 { 1343 1343 TCGMemOpIdx oi = l->oi; 1344 1344 TCGMemOp opc = get_memop(oi); ··· 1385 1385 } else { 1386 1386 tcg_out_opc_reg(s, OPC_OR, v0, TCG_REG_V0, TCG_REG_ZERO); 1387 1387 } 1388 + return true; 1388 1389 } 1389 1390 1390 - static void tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *l) 1391 + static bool tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *l) 1391 1392 { 1392 1393 TCGMemOpIdx oi = l->oi; 1393 1394 TCGMemOp opc = get_memop(oi); ··· 1435 1436 tcg_out_call_int(s, qemu_st_helpers[opc & (MO_BSWAP | MO_SIZE)], true); 1436 1437 /* delay slot */ 1437 1438 tcg_out_mov(s, TCG_TYPE_PTR, tcg_target_call_iarg_regs[0], TCG_AREG0); 1439 + return true; 1438 1440 } 1439 1441 #endif 1440 1442
+10 -4
tcg/ppc/tcg-target.inc.c
··· 1653 1653 label->label_ptr[0] = lptr; 1654 1654 } 1655 1655 1656 - static void tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *lb) 1656 + static bool tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *lb) 1657 1657 { 1658 1658 TCGMemOpIdx oi = lb->oi; 1659 1659 TCGMemOp opc = get_memop(oi); 1660 1660 TCGReg hi, lo, arg = TCG_REG_R3; 1661 1661 1662 - **lb->label_ptr |= reloc_pc14_val(*lb->label_ptr, s->code_ptr); 1662 + if (!reloc_pc14(lb->label_ptr[0], s->code_ptr)) { 1663 + return false; 1664 + } 1663 1665 1664 1666 tcg_out_mov(s, TCG_TYPE_PTR, arg++, TCG_AREG0); 1665 1667 ··· 1695 1697 } 1696 1698 1697 1699 tcg_out_b(s, 0, lb->raddr); 1700 + return true; 1698 1701 } 1699 1702 1700 - static void tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *lb) 1703 + static bool tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *lb) 1701 1704 { 1702 1705 TCGMemOpIdx oi = lb->oi; 1703 1706 TCGMemOp opc = get_memop(oi); 1704 1707 TCGMemOp s_bits = opc & MO_SIZE; 1705 1708 TCGReg hi, lo, arg = TCG_REG_R3; 1706 1709 1707 - **lb->label_ptr |= reloc_pc14_val(*lb->label_ptr, s->code_ptr); 1710 + if (!reloc_pc14(lb->label_ptr[0], s->code_ptr)) { 1711 + return false; 1712 + } 1708 1713 1709 1714 tcg_out_mov(s, TCG_TYPE_PTR, arg++, TCG_AREG0); 1710 1715 ··· 1753 1758 tcg_out_call(s, qemu_st_helpers[opc & (MO_BSWAP | MO_SIZE)]); 1754 1759 1755 1760 tcg_out_b(s, 0, lb->raddr); 1761 + return true; 1756 1762 } 1757 1763 #endif /* SOFTMMU */ 1758 1764
+12 -4
tcg/riscv/tcg-target.inc.c
··· 1065 1065 label->label_ptr[0] = label_ptr[0]; 1066 1066 } 1067 1067 1068 - static void tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *l) 1068 + static bool tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *l) 1069 1069 { 1070 1070 TCGMemOpIdx oi = l->oi; 1071 1071 TCGMemOp opc = get_memop(oi); ··· 1080 1080 } 1081 1081 1082 1082 /* resolve label address */ 1083 - patch_reloc(l->label_ptr[0], R_RISCV_BRANCH, (intptr_t) s->code_ptr, 0); 1083 + if (!patch_reloc(l->label_ptr[0], R_RISCV_BRANCH, 1084 + (intptr_t) s->code_ptr, 0)) { 1085 + return false; 1086 + } 1084 1087 1085 1088 /* call load helper */ 1086 1089 tcg_out_mov(s, TCG_TYPE_PTR, a0, TCG_AREG0); ··· 1092 1095 tcg_out_mov(s, (opc & MO_SIZE) == MO_64, l->datalo_reg, a0); 1093 1096 1094 1097 tcg_out_goto(s, l->raddr); 1098 + return true; 1095 1099 } 1096 1100 1097 - static void tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *l) 1101 + static bool tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *l) 1098 1102 { 1099 1103 TCGMemOpIdx oi = l->oi; 1100 1104 TCGMemOp opc = get_memop(oi); ··· 1111 1115 } 1112 1116 1113 1117 /* resolve label address */ 1114 - patch_reloc(l->label_ptr[0], R_RISCV_BRANCH, (intptr_t) s->code_ptr, 0); 1118 + if (!patch_reloc(l->label_ptr[0], R_RISCV_BRANCH, 1119 + (intptr_t) s->code_ptr, 0)) { 1120 + return false; 1121 + } 1115 1122 1116 1123 /* call store helper */ 1117 1124 tcg_out_mov(s, TCG_TYPE_PTR, a0, TCG_AREG0); ··· 1133 1140 tcg_out_call(s, qemu_st_helpers[opc & (MO_BSWAP | MO_SSIZE)]); 1134 1141 1135 1142 tcg_out_goto(s, l->raddr); 1143 + return true; 1136 1144 } 1137 1145 #endif /* CONFIG_SOFTMMU */ 1138 1146
+12 -8
tcg/s390/tcg-target.inc.c
··· 1609 1609 label->label_ptr[0] = label_ptr; 1610 1610 } 1611 1611 1612 - static void tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *lb) 1612 + static bool tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *lb) 1613 1613 { 1614 1614 TCGReg addr_reg = lb->addrlo_reg; 1615 1615 TCGReg data_reg = lb->datalo_reg; 1616 1616 TCGMemOpIdx oi = lb->oi; 1617 1617 TCGMemOp opc = get_memop(oi); 1618 1618 1619 - bool ok = patch_reloc(lb->label_ptr[0], R_390_PC16DBL, 1620 - (intptr_t)s->code_ptr, 2); 1621 - tcg_debug_assert(ok); 1619 + if (!patch_reloc(lb->label_ptr[0], R_390_PC16DBL, 1620 + (intptr_t)s->code_ptr, 2)) { 1621 + return false; 1622 + } 1622 1623 1623 1624 tcg_out_mov(s, TCG_TYPE_PTR, TCG_REG_R2, TCG_AREG0); 1624 1625 if (TARGET_LONG_BITS == 64) { ··· 1630 1631 tcg_out_mov(s, TCG_TYPE_I64, data_reg, TCG_REG_R2); 1631 1632 1632 1633 tgen_gotoi(s, S390_CC_ALWAYS, lb->raddr); 1634 + return true; 1633 1635 } 1634 1636 1635 - static void tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *lb) 1637 + static bool tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *lb) 1636 1638 { 1637 1639 TCGReg addr_reg = lb->addrlo_reg; 1638 1640 TCGReg data_reg = lb->datalo_reg; 1639 1641 TCGMemOpIdx oi = lb->oi; 1640 1642 TCGMemOp opc = get_memop(oi); 1641 1643 1642 - bool ok = patch_reloc(lb->label_ptr[0], R_390_PC16DBL, 1643 - (intptr_t)s->code_ptr, 2); 1644 - tcg_debug_assert(ok); 1644 + if (!patch_reloc(lb->label_ptr[0], R_390_PC16DBL, 1645 + (intptr_t)s->code_ptr, 2)) { 1646 + return false; 1647 + } 1645 1648 1646 1649 tcg_out_mov(s, TCG_TYPE_PTR, TCG_REG_R2, TCG_AREG0); 1647 1650 if (TARGET_LONG_BITS == 64) { ··· 1668 1671 tcg_out_call(s, qemu_st_helpers[opc & (MO_BSWAP | MO_SIZE)]); 1669 1672 1670 1673 tgen_gotoi(s, S390_CC_ALWAYS, lb->raddr); 1674 + return true; 1671 1675 } 1672 1676 #else 1673 1677 static void tcg_prepare_user_ldst(TCGContext *s, TCGReg *addr_reg,
+9 -9
tcg/tcg-ldst.inc.c
··· 38 38 * Generate TB finalization at the end of block 39 39 */ 40 40 41 - static void tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *l); 42 - static void tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *l); 41 + static bool tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *l); 42 + static bool tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *l); 43 43 44 - static bool tcg_out_ldst_finalize(TCGContext *s) 44 + static int tcg_out_ldst_finalize(TCGContext *s) 45 45 { 46 46 TCGLabelQemuLdst *lb; 47 47 48 48 /* qemu_ld/st slow paths */ 49 49 QSIMPLEQ_FOREACH(lb, &s->ldst_labels, next) { 50 - if (lb->is_ld) { 51 - tcg_out_qemu_ld_slow_path(s, lb); 52 - } else { 53 - tcg_out_qemu_st_slow_path(s, lb); 50 + if (lb->is_ld 51 + ? !tcg_out_qemu_ld_slow_path(s, lb) 52 + : !tcg_out_qemu_st_slow_path(s, lb)) { 53 + return -2; 54 54 } 55 55 56 56 /* Test for (pending) buffer overflow. The assumption is that any ··· 58 58 the buffer completely. Thus we can test for overflow after 59 59 generating code without having to check during generation. */ 60 60 if (unlikely((void *)s->code_ptr > s->code_gen_highwater)) { 61 - return false; 61 + return -1; 62 62 } 63 63 } 64 - return true; 64 + return 0; 65 65 } 66 66 67 67 /*
+4 -3
tcg/tcg.c
··· 128 128 static int tcg_target_const_match(tcg_target_long val, TCGType type, 129 129 const TCGArgConstraint *arg_ct); 130 130 #ifdef TCG_TARGET_NEED_LDST_LABELS 131 - static bool tcg_out_ldst_finalize(TCGContext *s); 131 + static int tcg_out_ldst_finalize(TCGContext *s); 132 132 #endif 133 133 134 134 #define TCG_HIGHWATER 1024 ··· 4000 4000 4001 4001 /* Generate TB finalization at the end of block */ 4002 4002 #ifdef TCG_TARGET_NEED_LDST_LABELS 4003 - if (!tcg_out_ldst_finalize(s)) { 4004 - return -1; 4003 + i = tcg_out_ldst_finalize(s); 4004 + if (i < 0) { 4005 + return i; 4005 4006 } 4006 4007 #endif 4007 4008 #ifdef TCG_TARGET_NEED_POOL_LABELS