diff --git a/hw/ub/hisi/trace-events b/hw/ub/hisi/trace-events index 44839d5091a63c912dd8d153eb64747a3b4ea584..6662887748f1c1d10124a0675c724dd9436e6830 100644 --- a/hw/ub/hisi/trace-events +++ b/hw/ub/hisi/trace-events @@ -2,6 +2,7 @@ # ubc_msgq.c handle_eu_table_cfg_cmd(uint32_t msg_code, uint32_t entry_num, uint32_t tbl_cfg_mode, uint32_t tbl_cfg_status, uint32_t entry_start_id, uint32_t eid, uint32_t upi) "eu_msg_code(%u), cfg_entry_num(%u), tbl_cfg_mode(%u), tbl_cfg_status(%u), entry_start_id(%u), eid(%u), upi(%u)" -msgq_sq_init(uint64_t gpa, uint32_t depth) "sq_base_addr_gpa 0x%lx depth %u" -msgq_cq_init(uint64_t gpa, uint32_t depth) "cq_base_addr_gpa 0x%lx depth %u" -msgq_rq_init(uint64_t gpa, uint32_t depth) "rq_base_addr_gpa 0x%lx depth %u" +msgq_sq_init(uint64_t gpa, uint32_t depth, uint64_t size) "sq_base_addr_gpa 0x%lx depth %u size %lu" +msgq_cq_init(uint64_t gpa, uint32_t depth, uint64_t size) "cq_base_addr_gpa 0x%lx depth %u size %lu" +msgq_rq_init(uint64_t gpa, uint32_t depth, uint64_t size) "rq_base_addr_gpa 0x%lx depth %u size %lu" +paddr_is_validate(uint32_t start, uint32_t end, uint32_t paddr) "start 0x%x end 0x%x paddr 0x%x" diff --git a/hw/ub/hisi/ubc_msgq.c b/hw/ub/hisi/ubc_msgq.c index c393957d78a3e315153182acb36851bef952a383..28a35bb43f1b6a6f486ddffc65afa21a48038f68 100644 --- a/hw/ub/hisi/ubc_msgq.c +++ b/hw/ub/hisi/ubc_msgq.c @@ -69,6 +69,21 @@ static void (*msgq_handlers[])(void *opaque, HiMsgSqe *sqe, void *payload) = { [UB_MSG_CODE_POOL] = handle_msg_pool, }; +static bool paddr_is_validate(BusControllerState *s, uint32_t paddr) +{ + uint32_t payload_start_offset = s->msgq.sq_depth * HI_MSG_SQE_SIZE;; + uint32_t payload_end_offset = s->msgq.sq_sz; + + if (paddr < payload_start_offset || paddr > payload_end_offset - HI_MSG_SQE_PLD_SIZE) { + qemu_log("invalid paddr %u, expect paddr in [0x%x, 0x%x]\n", + paddr, payload_start_offset, payload_end_offset); + return false; + } + trace_paddr_is_validate(payload_start_offset, payload_end_offset, paddr); + + return true; +} + static void handle_task_type_msg(BusControllerState *s, HiMsgSqe *sqe) { MsgPktHeader *payload = NULL; @@ -82,12 +97,12 @@ static void handle_task_type_msg(BusControllerState *s, HiMsgSqe *sqe) return; } - if (p_addr + HI_MSG_SQE_PLD_SIZE > s->msgq.sq_sz) { - qemu_log("invalid p_addr %u, total size %ld\n", - p_addr, s->msgq.sq_sz); + if (!paddr_is_validate(s, p_addr)) { + qemu_log("invalid p_addr 0x%x\n", p_addr); return; } + assert(HI_MSG_SQE_PLD_SIZE > sizeof(MsgPktHeader)); payload = g_malloc0(sizeof(MsgPktHeader)); if (dma_memory_read(&address_space_memory, s->msgq.sq_base_addr_gpa + p_addr, payload, sizeof(MsgPktHeader), MEMTXATTRS_UNSPECIFIED)) { @@ -97,6 +112,13 @@ static void handle_task_type_msg(BusControllerState *s, HiMsgSqe *sqe) } plen = payload->msgetah.plen; g_free(payload); + + if (HI_MSG_SQE_PLD_SIZE - sizeof(MsgPktHeader) < plen) { + qemu_log("unexpect msgq seq ply size(0x%x) - MsgPktHeader(0x%lx) < plen(0x%x)\n", + HI_MSG_SQE_PLD_SIZE, sizeof(MsgPktHeader), plen); + return; + } + payload = g_malloc0(sizeof(MsgPktHeader) + plen); if (dma_memory_read(&address_space_memory, s->msgq.sq_base_addr_gpa + p_addr, payload, sizeof(MsgPktHeader) + plen, MEMTXATTRS_UNSPECIFIED)) { @@ -118,9 +140,8 @@ static void handle_task_type_enum(BusControllerState *s, HiMsgSqe *sqe) void *payload = NULL; uint32_t p_addr = sqe->p_addr; - if (p_addr + HI_MSG_SQE_PLD_SIZE > s->msgq.sq_sz) { - qemu_log("invalid p_addr %u, total size %ld\n", - p_addr, s->msgq.sq_sz); + if (!paddr_is_validate(s, p_addr)) { + qemu_log("invalid p_addr 0x%x\n", p_addr); return; } @@ -171,12 +192,12 @@ static void handle_task_type_hisi_private(BusControllerState *s, HiMsgSqe *sqe) return; } - if (p_addr + HI_MSG_SQE_PLD_SIZE > s->msgq.sq_sz) { - qemu_log("invalid p_addr %u, total size %ld\n", - p_addr, s->msgq.sq_sz); + if (!paddr_is_validate(s, p_addr)) { + qemu_log("invalid p_addr 0x%x\n", p_addr); return; } + assert(HI_MSG_SQE_PLD_SIZE > sizeof(HiEuCfgReq)); payload = g_malloc0(sizeof(HiEuCfgReq)); if (dma_memory_read(&address_space_memory, s->msgq.sq_base_addr_gpa + p_addr, payload, sizeof(HiEuCfgReq), MEMTXATTRS_UNSPECIFIED)) { @@ -201,14 +222,14 @@ void msgq_process_task(void *opaque, uint64_t val) uint16_t cnt; uint32_t ci = ub_get_long(s->msgq_reg + SQ_CI); uint32_t pi = ub_get_long(s->msgq_reg + SQ_PI); - uint32_t depth = ub_get_long(s->msgq_reg + SQ_DEPTH); + uint32_t depth = s->msgq.sq_depth; if (!s->msgq.sq_base_addr_gpa) { /* not ready */ return; } - if (depth > HI_MSGQ_MAX_DEPTH || depth < HI_MSGQ_MIN_DEPTH || ci >= depth || pi >= depth) { + if (ci >= depth || pi >= depth) { qemu_log("Invalid arguments: ci=%u pi=%u depth=%u\n", ci, pi, depth); return; } @@ -255,16 +276,32 @@ void msgq_sq_init(void *opaque) uint32_t addr_l = ub_get_long(s->msgq_reg + SQ_ADDR_L); uint32_t addr_h = ub_get_long(s->msgq_reg + SQ_ADDR_H); uint32_t depth = ub_get_long(s->msgq_reg + SQ_DEPTH); - uint64_t size = (uint64_t)depth * (HI_MSG_SQE_SIZE + HI_MSG_SQE_PLD_SIZE); + uint64_t size = 0; + uint64_t sq_base_addr_gpa = addr_l | ((uint64_t)addr_h << 32); + + if (s->msgq.sq_inited) { + qemu_log("cannot init msgq repeat: gpa(0x%" PRIu64 "), depth(%u)\n", + sq_base_addr_gpa, depth); + return; + } + + if (depth > HI_MSGQ_MAX_DEPTH || depth < HI_MSGQ_MIN_DEPTH) { + qemu_log("invalid depth value %u, expect depth [%u, %u]\n", + depth, HI_MSGQ_MIN_DEPTH, HI_MSGQ_MAX_DEPTH); + return; + } - s->msgq.sq_base_addr_gpa = addr_l | ((uint64_t)addr_h << 32); - if (size != depth * (HI_MSG_SQE_SIZE + HI_MSG_SQE_PLD_SIZE)) { - qemu_log("sq size %lu != %lu, depth=%u\n", size, - depth * (HI_MSG_SQE_SIZE + HI_MSG_SQE_PLD_SIZE), depth); + if (sq_base_addr_gpa == 0) { + qemu_log("invalid sq_base_addr_gpa is 0\n"); return; } + + size = (uint64_t)depth * (HI_MSG_SQE_SIZE + HI_MSG_SQE_PLD_SIZE); s->msgq.sq_sz = size; - trace_msgq_sq_init(s->msgq.sq_base_addr_gpa, depth); + s->msgq.sq_depth = depth; + s->msgq.sq_base_addr_gpa = sq_base_addr_gpa; + s->msgq.sq_inited = true; + trace_msgq_sq_init(sq_base_addr_gpa, depth, size); } void msgq_cq_init(void *opaque) @@ -273,16 +310,32 @@ void msgq_cq_init(void *opaque) uint32_t addr_l = ub_get_long(s->msgq_reg + CQ_ADDR_L); uint32_t addr_h = ub_get_long(s->msgq_reg + CQ_ADDR_H); uint32_t depth = ub_get_long(s->msgq_reg + CQ_DEPTH); - uint64_t size = (uint64_t)depth * HI_MSG_CQE_SIZE; + uint64_t size = 0; + uint64_t cq_base_addr_gpa = addr_l | ((uint64_t)addr_h << 32); + + if (s->msgq.cq_inited) { + qemu_log("cannot init msgq repeat: gpa(0x%" PRIu64 "), depth(%u)\n", + cq_base_addr_gpa, depth); + return; + } + + if (depth > HI_MSGQ_MAX_DEPTH || depth < HI_MSGQ_MIN_DEPTH) { + qemu_log("invalid depth value %u, expect depth [%u, %u]\n", + depth, HI_MSGQ_MIN_DEPTH, HI_MSGQ_MAX_DEPTH); + return; + } - s->msgq.cq_base_addr_gpa = addr_l | ((uint64_t)addr_h << 32); - if (size != depth * HI_MSG_CQE_SIZE) { - qemu_log("cq size %lu != %lu, depth=%u\n", size, - depth * HI_MSG_CQE_SIZE, depth); + if (cq_base_addr_gpa == 0) { + qemu_log("invalid cq_base_addr_gpa is 0\n"); return; } + + size = (uint64_t)depth * (HI_MSG_SQE_SIZE + HI_MSG_SQE_PLD_SIZE); s->msgq.cq_sz = size; - trace_msgq_cq_init(s->msgq.cq_base_addr_gpa, depth); + s->msgq.cq_depth = depth; + s->msgq.cq_base_addr_gpa = cq_base_addr_gpa; + s->msgq.cq_inited = true; + trace_msgq_cq_init(cq_base_addr_gpa, depth, size); } void msgq_rq_init(void *opaque) @@ -291,25 +344,39 @@ void msgq_rq_init(void *opaque) uint32_t addr_l = ub_get_long(s->msgq_reg + RQ_ADDR_L); uint32_t addr_h = ub_get_long(s->msgq_reg + RQ_ADDR_H); uint32_t depth = ub_get_long(s->msgq_reg + RQ_DEPTH); - uint64_t size = (uint64_t)depth * HI_MSG_RQE_SIZE; + uint64_t size = 0; + uint64_t rq_base_addr_gpa = addr_l | ((uint64_t)addr_h << 32); + + if (s->msgq.rq_inited) { + qemu_log("cannot init msgq repeat: gpa(0x%" PRIu64 "), depth(%u)\n", + rq_base_addr_gpa, depth); + return; + } - s->msgq.rq_base_addr_gpa = addr_l | ((uint64_t)addr_h << 32); - if (size != depth * HI_MSG_RQE_SIZE) { - qemu_log("rq size %lu != %u, depth=%u\n", size, - depth * HI_MSG_RQE_SIZE, depth); + if (depth > HI_MSGQ_MAX_DEPTH || depth < HI_MSGQ_MIN_DEPTH) { + qemu_log("invalid depth value %u, expect depth [%u, %u]\n", + depth, HI_MSGQ_MIN_DEPTH, HI_MSGQ_MAX_DEPTH); return; } + + if (rq_base_addr_gpa == 0) { + qemu_log("invalid cq_base_addr_gpa is 0\n"); + return; + } + + size = (uint64_t)depth * (HI_MSG_SQE_SIZE + HI_MSG_SQE_PLD_SIZE); s->msgq.rq_sz = size; - trace_msgq_rq_init(s->msgq.rq_base_addr_gpa, depth); + s->msgq.rq_depth = depth; + s->msgq.rq_base_addr_gpa = rq_base_addr_gpa; + s->msgq.rq_inited = true; + trace_msgq_rq_init(rq_base_addr_gpa, depth, size); } void msgq_handle_rst(void *opaque) { BusControllerState *s = opaque; - uint32_t old = ub_get_long(s->msgq_reg + SQ_CI); - qemu_log("BusControllerState receive reset event, " - "clear SQ_CI(%u -> 0).\n", old); + qemu_log("BusControllerState receive reset event, clear msgq reg info to 0.\n"); ub_set_long(s->msgq_reg + SQ_CI, 0); ub_set_long(s->msgq_reg + SQ_ADDR_L, 0); ub_set_long(s->msgq_reg + SQ_ADDR_H, 0); diff --git a/hw/ub/ub_cna_mgmt.c b/hw/ub/ub_cna_mgmt.c index 1f74cbdb65135da3b3ec3b896fe414e022fedd05..fef1ccb663eff1e4b6ce0b74e214cd27113ac8f6 100644 --- a/hw/ub/ub_cna_mgmt.c +++ b/hw/ub/ub_cna_mgmt.c @@ -77,6 +77,7 @@ void handle_enum_cna_config_request(BusControllerState *s, HiMsgCqe cqe; char guid[UB_DEV_GUID_STRING_LENGTH + 1] = {0}; + assert(HI_MSG_SQE_PLD_SIZE > ENUM_PKT_HEADER_SIZE + sizeof(EnumPldScanHeader)); scan_header = g_malloc0(sizeof(EnumPldScanHeader)); if (dma_memory_read(&address_space_memory, (unsigned long)(buf + ENUM_PKT_HEADER_SIZE), @@ -85,7 +86,15 @@ void handle_enum_cna_config_request(BusControllerState *s, g_free(scan_header); return; } + header_sz = ENUM_PKT_HEADER_SIZE + calc_enum_pld_header_size(scan_header, true) + ENUM_NA_CFG_REQ_SIZE; + if (HI_MSG_SQE_PLD_SIZE < header_sz) { + qemu_log("unexpect msgq sqe pld size(0x%x) < prepare read payload size(0x%lx)\n", + HI_MSG_SQE_PLD_SIZE, header_sz); + g_free(scan_header); + return; + } + g_free(scan_header); payload = g_malloc0(header_sz); if (dma_memory_read(&address_space_memory, (unsigned long)(buf), @@ -169,6 +178,7 @@ void handle_enum_cna_query_request(BusControllerState *s, uint64_t emulated_offset; size_t forward_path_size; + assert(HI_MSG_SQE_PLD_SIZE > ENUM_PKT_HEADER_SIZE + sizeof(EnumPldScanHeader)); scan_header = g_malloc0(sizeof(EnumPldScanHeader)); if (dma_memory_read(&address_space_memory, (unsigned long)(buf + ENUM_PKT_HEADER_SIZE), @@ -177,7 +187,15 @@ void handle_enum_cna_query_request(BusControllerState *s, g_free(scan_header); return; } + header_sz = ENUM_PKT_HEADER_SIZE + calc_enum_pld_header_size(scan_header, true) + ENUM_NA_QRY_REQ_SIZE; + if (HI_MSG_SQE_PLD_SIZE < header_sz) { + qemu_log("unexpect msgq sqe pld size(0x%x) < prepare read payload size(0x%lx)\n", + HI_MSG_SQE_PLD_SIZE, header_sz); + g_free(scan_header); + return; + } + g_free(scan_header); payload = g_malloc0(header_sz); if (dma_memory_read(&address_space_memory, (unsigned long)(buf), diff --git a/hw/ub/ub_common.c b/hw/ub/ub_common.c index f8ef12fb026f1075368f12af71a40ffab6515553..3439592072080c7522c886c378dad5e5af94dc5a 100644 --- a/hw/ub/ub_common.c +++ b/hw/ub/ub_common.c @@ -29,7 +29,7 @@ uint32_t fill_rq(BusControllerState *s, void *rsp, uint32_t rsp_size) uint32_t ci = ub_get_long(s->msgq_reg + RQ_CI); uint32_t pi = ub_get_long(s->msgq_reg + RQ_PI); uint32_t pi_new; - uint32_t depth = ub_get_long(s->msgq_reg + RQ_DEPTH); + uint32_t depth = s->msgq.rq_depth; uint32_t remain; hwaddr dst_rqe; @@ -38,7 +38,7 @@ uint32_t fill_rq(BusControllerState *s, void *rsp, uint32_t rsp_size) return UINT32_MAX; } - if (depth > HI_MSGQ_MAX_DEPTH || depth < HI_MSGQ_MIN_DEPTH || ci >= depth || pi >= depth) { + if (ci >= depth || pi >= depth) { qemu_log("Invalid RQ indices: ci=%u pi=%u depth=%u\n", ci, pi, depth); return UINT32_MAX; } @@ -61,11 +61,11 @@ uint32_t fill_cq(BusControllerState *s, HiMsgCqe *cqe) { uint32_t ci = ub_get_long(s->msgq_reg + CQ_CI); uint32_t pi = ub_get_long(s->msgq_reg + CQ_PI); - uint32_t depth = ub_get_long(s->msgq_reg + CQ_DEPTH); + uint32_t depth = s->msgq.rq_depth; uint32_t remain; hwaddr dst_cqe; - if (depth > HI_MSGQ_MAX_DEPTH || depth < HI_MSGQ_MIN_DEPTH || ci >= depth || pi >= depth) { + if (ci >= depth || pi >= depth) { qemu_log("Invalid CQ indices: ci=%u pi=%u depth=%u\n", ci, pi, depth); return UINT32_MAX; } diff --git a/hw/ub/ub_config.c b/hw/ub/ub_config.c index 971984432f1cf5d3f4347325fe4da212d616efe8..7451f1a133a9a02abd50f5059718d093e8dc57ef 100644 --- a/hw/ub/ub_config.c +++ b/hw/ub/ub_config.c @@ -202,11 +202,11 @@ static uint32_t get_dw_mask(uint8_t byte_enable) static void ub_cfg_rw(BusControllerState *s, HiMsgSqe *sqe, MsgPktHeader *header) { - CfgMsgPldReq *payload = (CfgMsgPldReq *)header->payload; + CfgMsgPldReq *payload = NULL; CfgMsgPkt rsp_pkt; uint32_t local = sqe->local; - uint64_t cfg_offset = (uint64_t)payload->req_addr * DWORD_SIZE; - uint32_t entity = payload->entity_idx; + uint64_t cfg_offset = 0; + uint32_t entity = 0; uint32_t dcna = header->nth.dcna; UBDevice *ub_dev = NULL; uint32_t dw_mask; @@ -217,6 +217,9 @@ static void ub_cfg_rw(BusControllerState *s, HiMsgSqe *sqe, header->msgetah.plen); return; } + payload = (CfgMsgPldReq *)header->payload; + cfg_offset = (uint64_t)payload->req_addr * DWORD_SIZE; + entity = payload->entity_idx; memset(&rsp_pkt, 0, sizeof(CfgMsgPkt)); memcpy(&rsp_pkt.header, header, sizeof(MsgPktHeader)); diff --git a/hw/ub/ub_enum.c b/hw/ub/ub_enum.c index 8e145e8f2d89196757d496d886def6ad7f484b6b..6dad22997ac8ab2459f7981ce049e0d3d85a830d 100644 --- a/hw/ub/ub_enum.c +++ b/hw/ub/ub_enum.c @@ -178,6 +178,7 @@ static void handle_enum_query_request(BusControllerState *s, HiMsgSqe *sqe, EnumTopoQueryRspPdu *rsp_pdu; HiMsgCqe cqe; + assert(HI_MSG_SQE_PLD_SIZE > ENUM_PKT_HEADER_SIZE + sizeof(EnumPldScanHeader)); scan_header = g_malloc0(sizeof(EnumPldScanHeader)); if (dma_memory_read(&address_space_memory, (unsigned long)(buf + ENUM_PKT_HEADER_SIZE), @@ -186,7 +187,15 @@ static void handle_enum_query_request(BusControllerState *s, HiMsgSqe *sqe, g_free(scan_header); return; } + header_sz = ENUM_PKT_HEADER_SIZE + calc_enum_pld_header_size(scan_header, true) + ENUM_TOPO_QUERY_REQ_SIZE; + if (HI_MSG_SQE_PLD_SIZE < header_sz) { + qemu_log("unexpect msgq sqe pld size(0x%x) < prepare read payload size(0x%lx)\n", + HI_MSG_SQE_PLD_SIZE, header_sz); + g_free(scan_header); + return; + } + g_free(scan_header); payload = g_malloc0(header_sz); if (dma_memory_read(&address_space_memory, (unsigned long)(buf), diff --git a/include/hw/ub/hisi/ubc.h b/include/hw/ub/hisi/ubc.h index c94759956e068b10c62ff35b3214cde7a06417f0..e423b0b26a25d36d7ea651f3cb199ccb2409e7eb 100644 --- a/include/hw/ub/hisi/ubc.h +++ b/include/hw/ub/hisi/ubc.h @@ -289,10 +289,16 @@ typedef struct HiMsgSqePld { typedef struct HiMsgqInfo { uint64_t sq_base_addr_gpa; uint64_t sq_sz; + uint32_t sq_depth; + bool sq_inited; uint64_t cq_base_addr_gpa; uint64_t cq_sz; + uint32_t cq_depth; + bool cq_inited; uint64_t rq_base_addr_gpa; uint64_t rq_sz; + uint32_t rq_depth; + bool rq_inited; } HiMsgqInfo; typedef enum HiMsgqIdx {