linux-mm.kvack.org archive mirror
 help / color / mirror / Atom feed
* Allocating mock memory resources
@ 2017-04-16  6:31 Pavel Roskin
  2017-04-21 19:02 ` Pavel Roskin
  0 siblings, 1 reply; 2+ messages in thread
From: Pavel Roskin @ 2017-04-16  6:31 UTC (permalink / raw)
  To: linux-mm

Hello!

I'm working on a device driver for hardware that is being developed.
I'm coding against the specification and hoping for the best. It would
be very handy to have a mock implementation of the hardware so I could
test the driver against it. In the end, it would be an integration
test for the driver, which could be useful even after the hardware
arrives. For example, I could emulate hardware failures and see how
the driver reacts. Moreover, a driver test framework would be useful
for others.

One issue I'm facing is creating resources for the device. Luckily,
the driver only needs memory resources. It should be simple to
allocate such resources in system RAM, but I could not find a good way
to do it. Either the resource allocation fails, or the kernel panics
right away, or it panics when I run "cat /proc/iomem"

I ended up limiting the memory available to the kernel using the
"mem=" directive and hardcoding the address pointing to RAM beyond
what the kernel uses. I would prefer to have an approach that doesn't
require changes to the kernel command line. It there a safe way to
allocate a memory resource in system RAM?

-- 
Regards,
Pavel Roskin

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: Allocating mock memory resources
  2017-04-16  6:31 Allocating mock memory resources Pavel Roskin
@ 2017-04-21 19:02 ` Pavel Roskin
  0 siblings, 0 replies; 2+ messages in thread
From: Pavel Roskin @ 2017-04-21 19:02 UTC (permalink / raw)
  To: linux-mm

Hello

On Sat, Apr 15, 2017 at 11:31 PM, Pavel Roskin <plroskin@gmail.com> wrote:

> I'm working on a device driver for hardware that is being developed.
> I'm coding against the specification and hoping for the best. It would
> be very handy to have a mock implementation of the hardware so I could
> test the driver against it. In the end, it would be an integration
> test for the driver, which could be useful even after the hardware
> arrives. For example, I could emulate hardware failures and see how
> the driver reacts. Moreover, a driver test framework would be useful
> for others.
>
> One issue I'm facing is creating resources for the device. Luckily,
> the driver only needs memory resources. It should be simple to
> allocate such resources in system RAM, but I could not find a good way
> to do it. Either the resource allocation fails, or the kernel panics
> right away, or it panics when I run "cat /proc/iomem"

In case anybody cares, here's my working solution.

The RAM resource is needed because request_region() cannot traverse
busy RAM region, but request_resource() doesn't check if any resources
are busy. I don't like iterating over resources in a driver, but I
don't know a better approach. I assume that all system RAM resources
are direct children of iomem_resource.

SetPageReserved() is needed to allow ioremap() on the region (by the
way, CamelCase in the kernel code looks so weird).

I'm surprised there is no universal phys_to_page() macro, so I'm using
virtual addresses to iterate over pages.

The only limitation on the driver under test is that it should not be
using request_region() on iomem_resource, as the RAM resource is busy
and cannot be traversed.


static struct resource *fff_get_ram_resource(struct resource *res)
{
    resource_size_t start = res->start;
    resource_size_t end = res->end;
    struct resource *p;

    for (p = iomem_resource.child; p && p->start <= end; p = p->sibling) {
        if (p->end >= start)
            return p;
    }

    return NULL;
}

static int __init fff_emu_alloc_resources(void)
{
    struct page *pg;
    char *pg_base, *p;
    struct resource *ram_res;
    int ret;

    pg = alloc_pages(GFP_KERNEL | __GFP_ZERO, get_order(EMU_MEM_SIZE));
    if (!pg) {
        pr_err("Cannot allocate memory for emulator resource\n");
        return -ENOMEM;
    }

    pg_base = page_to_virt(pg);

    emu_mem.start = page_to_phys(pg);
    emu_mem.end = emu_mem.start + EMU_MEM_SIZE - 1;

    ram_res = fff_get_ram_resource(&emu_mem);
    if (!ram_res) {
        pr_err("no RAM resource found for %pR\n", &emu_mem);
        ret = -ENXIO;
        goto out_mem;
    }

    ret = request_resource(ram_res, &emu_mem);
    if (ret) {
        pr_err("request_resource failed on %pR under %pR: error %d\n",
               &emu_mem, ram_res, ret);
        goto out_mem;
    }

    for (p = pg_base; p < pg_base + EMU_MEM_SIZE; p += PAGE_SIZE)
        SetPageReserved(virt_to_page(p));

    return 0;

out_mem:
    free_pages((unsigned long)pg_base, get_order(EMU_MEM_SIZE));
    return ret;
}

static void fff_emu_free_resources(void)
{
    char *pg_base, *p;

    pg_base = __va(emu_mem.start);
    release_resource(&emu_mem);

    for (p = pg_base; p < pg_base + EMU_MEM_SIZE; p += PAGE_SIZE)
        ClearPageReserved(virt_to_page(p));

    free_pages((unsigned long)pg_base, get_order(EMU_MEM_SIZE));
}



-- 
Regards,
Pavel Roskin

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2017-04-21 19:02 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-04-16  6:31 Allocating mock memory resources Pavel Roskin
2017-04-21 19:02 ` Pavel Roskin

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox