On 6/8/2024 12:02 AM, Peter Maydell wrote:
On Mon, 3 Jun 2024 at 09:38, Jeuk Kim <jeuk20....@gmail.com> wrote:
From: Minwoo Im <minwoo...@samsung.com>
This patch adds support for MCQ defined in UFSHCI 4.0. This patch
utilized the legacy I/O codes as much as possible to support MCQ.
MCQ operation & runtime register is placed at 0x1000 offset of UFSHCI
register statically with no spare space among four registers (48B):
UfsMcqSqReg, UfsMcqSqIntReg, UfsMcqCqReg, UfsMcqCqIntReg
The maxinum number of queue is 32 as per spec, and the default
MAC(Multiple Active Commands) are 32 in the device.
Example:
-device ufs,serial=foo,id=ufs0,mcq=true,mcq-maxq=8
Signed-off-by: Minwoo Im <minwoo...@samsung.com>
Reviewed-by: Jeuk Kim <jeuk20....@samsung.com>
Message-Id: <20240528023106.856777-3-minwoo...@samsung.com>
Signed-off-by: Jeuk Kim <jeuk20....@samsung.com>
Hi; Coverity reported a potential issue with this code.
I don't think it's an actual bug, but it would be nice to
clean it up and keep Coverity happy. (CID 1546866).
static uint64_t ufs_mmio_read(void *opaque, hwaddr addr, unsigned size)
{
UfsHc *u = (UfsHc *)opaque;
- uint8_t *ptr = (uint8_t *)&u->reg;
+ uint8_t *ptr;
uint64_t value;
-
- if (addr > sizeof(u->reg) - size) {
Before this change, we checked addr against (sizeof(u->reg) - size).
+ uint64_t offset;
+
+ if (addr < sizeof(u->reg)) {
Now we changed to check it against sizeof(u->reg).
That means Coverity thinks it's possible that we could
have addr = sizeof(u->reg) - 1...
+ offset = addr;
+ ptr = (uint8_t *)&u->reg;
+ } else if (ufs_is_mcq_reg(u, addr)) {
+ offset = addr - ufs_mcq_reg_addr(u, 0);
+ ptr = (uint8_t *)&u->mcq_reg;
+ } else if (ufs_is_mcq_op_reg(u, addr)) {
+ offset = addr - ufs_mcq_op_reg_addr(u, 0);
+ ptr = (uint8_t *)&u->mcq_op_reg;
+ } else {
trace_ufs_err_invalid_register_offset(addr);
return 0;
}
- value = *(uint32_t *)(ptr + addr);
+ value = *(uint32_t *)(ptr + offset);
...so Coverity thinks that this write of a 32-bit value
might overrun the end of the array.
trace_ufs_mmio_read(addr, value, size);
return value;
Side note: why use uint8_t* for the type of "ptr" in these
functions? We know it must be a uint32_t* (it comes either from
the u->reg or from one of these u_mcq_reg or u->mcq_op_reg
fields, and they must all be uint32_t), and using the right
type would reduce the number of casts you need to do.
This is probably to make the offset calculation easier (since we can
write `addr + offset` instead of `addr + offset/4`). But I agree with
you that it can be semantically confusing. I'll fix it.
It also helps the reader a little, because using a uint8_t
implies that you're indexing into an array-of-bytes, and
if you were doing that it would be a bug (because both of
it not handling endianness correctly and because of it
not handling alignment correctly).
}
@@ -423,13 +802,17 @@ static void ufs_mmio_write(void *opaque, hwaddr addr,
uint64_t data,
{
UfsHc *u = (UfsHc *)opaque;
- if (addr > sizeof(u->reg) - size) {
+ trace_ufs_mmio_write(addr, data, size);
+
+ if (addr < sizeof(u->reg)) {
Similarly here we changed the bounds check we were doing.
+ ufs_write_reg(u, addr, data, size);
+ } else if (ufs_is_mcq_reg(u, addr)) {
+ ufs_write_mcq_reg(u, addr - ufs_mcq_reg_addr(u, 0), data, size);
+ } else if (ufs_is_mcq_op_reg(u, addr)) {
+ ufs_write_mcq_op_reg(u, addr - ufs_mcq_op_reg_addr(u, 0), data, size);
+ } else {
trace_ufs_err_invalid_register_offset(addr);
- return;
}
-
- trace_ufs_mmio_write(addr, data, size);
- ufs_write_reg(u, addr, data, size);
thanks
-- PMM
Thanks for the detailed explanation! I will prepare a patch to fix the
coverity issue.
Thanks,
Jeuk