qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Qemu-devel] [PATCH v8 18/23] RISC-V VirtIO Machine


From: Michael Clark
Subject: Re: [Qemu-devel] [PATCH v8 18/23] RISC-V VirtIO Machine
Date: Mon, 30 Apr 2018 12:18:48 +1200

On Sat, Apr 28, 2018 at 2:17 AM, Peter Maydell <address@hidden>
wrote:

> On 2 March 2018 at 13:51, Michael Clark <address@hidden> wrote:
> > RISC-V machine with device-tree, 16550a UART and VirtIO MMIO.
> > The following machine is implemented:
> >
> > - 'virt'; CLINT, PLIC, 16550A UART, VirtIO MMIO, device-tree
> >
> > Acked-by: Richard Henderson <address@hidden>
> > Signed-off-by: Palmer Dabbelt <address@hidden>
> > Signed-off-by: Michael Clark <address@hidden>
>
> Hi; Coverity spots (CID 1390606) that in this function you
> leak a little bit of memory:
>
> > +static void riscv_virt_board_init(MachineState *machine)
> > +{
>
> > +    /* create PLIC hart topology configuration string */
> > +    plic_hart_config_len = (strlen(VIRT_PLIC_HART_CONFIG) + 1) *
> smp_cpus;
> > +    plic_hart_config = g_malloc0(plic_hart_config_len);
>
> Here we allocate memory into plic_hart_config...
>
> > +    for (i = 0; i < smp_cpus; i++) {
> > +        if (i != 0) {
> > +            strncat(plic_hart_config, ",", plic_hart_config_len);
> > +        }
> > +        strncat(plic_hart_config, VIRT_PLIC_HART_CONFIG,
> plic_hart_config_len);
> > +        plic_hart_config_len -= (strlen(VIRT_PLIC_HART_CONFIG) + 1);
> > +    }
> > +
> > +    /* MMIO */
> > +    s->plic = sifive_plic_create(memmap[VIRT_PLIC].base,
> > +        plic_hart_config,
>
> (and this function doesn't take ownership of the string)
>
> > +        VIRT_PLIC_NUM_SOURCES,
> > +        VIRT_PLIC_NUM_PRIORITIES,
> > +        VIRT_PLIC_PRIORITY_BASE,
> > +        VIRT_PLIC_PENDING_BASE,
> > +        VIRT_PLIC_ENABLE_BASE,
> > +        VIRT_PLIC_ENABLE_STRIDE,
> > +        VIRT_PLIC_CONTEXT_BASE,
> > +        VIRT_PLIC_CONTEXT_STRIDE,
> > +        memmap[VIRT_PLIC].size);
> > +    sifive_clint_create(memmap[VIRT_CLINT].base,
> > +        memmap[VIRT_CLINT].size, smp_cpus,
> > +        SIFIVE_SIP_BASE, SIFIVE_TIMECMP_BASE, SIFIVE_TIME_BASE);
> > +    sifive_test_create(memmap[VIRT_TEST].base);
> > +
> > +    for (i = 0; i < VIRTIO_COUNT; i++) {
> > +        sysbus_create_simple("virtio-mmio",
> > +            memmap[VIRT_VIRTIO].base + i * memmap[VIRT_VIRTIO].size,
> > +            SIFIVE_PLIC(s->plic)->irqs[VIRTIO_IRQ + i]);
> > +    }
> > +
> > +    serial_mm_init(system_memory, memmap[VIRT_UART0].base,
> > +        0, SIFIVE_PLIC(s->plic)->irqs[UART0_IRQ], 399193,
> > +        serial_hds[0], DEVICE_LITTLE_ENDIAN);
>
> ...but we don't free the memory before leaving.
>
> > +}
>
> Not a big deal since this function is only run once, but adding
> in the necessary g_free(plic_hart_config) will placate Coverity.
>
>
Didn't mean to go off list. I'm adding Alastair as he is looking at
refactoring the machines to use QOM for an SOC holding the devices,
separate from the machine state structure.

Quite a bit of our initialization code in several QOM classes allocate
memory that is not freed. e.g. the PLIC. Usually these functions are only
run once, but ideally all of the code should be memory clean. i.e. exit
without leaks. Many programs don't bother with this but I think it is a
good practice.

Should we use dc->unrealize to point to an unrelalize function that calls
g_free? Is unrealize the QOM destructor?

As an aside, for Alastair's sake. We intend to implement and generalize ISA
string parsing so that RISCVHartArray is indeed heterogeneous and the PLIC
can figure out its dimensions from RISCVHartArray. Once the CPUs are
realized, we can derive the modes that a CPU/hart supports from 'misa'. The
RTL designers for the SiFive PLIC made a decision to save address space
versus using 2-bits in the interrupt configuration address space to encode
mode (with reserved areas for unsupported modes). With the current compact
address space layout, we need to know which modes a hart (hardware thread)
supports to see how much address space it uses in the PLIC configuration
aperture, and each CPU can have a variable sized aperture depending on the
modes it supports. This complicates dynamic address decode as we can't
simply use ranges of bits to get mode and hart. The RTL generates the
address decode statically from the core complex configuration so it's not
an issue in hardware, although one would wonder whether it might use more
comparators in its address decode logic. Also of note, is that we may add
an option to the PLIC that inverts the dimensions from { hart, mode } to {
mode, hart } so that M mode can use PMP to protect its interrupt routing
configuration. Presently the modes are interleaved instead of having per
per mode apertures (which is required for virtualization of the PLIC). That
requirement (dimension order) would dictate a more regular address space
layout.


reply via email to

[Prev in Thread] Current Thread [Next in Thread]