qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Blue Swirl <blauwirbel@gmail.com>
To: Richard Henderson <rth@twiddle.net>
Cc: paul@codesourcery.com, agraf@suse.de, qemu-devel@nongnu.org
Subject: Re: [Qemu-devel] [PATCH 0/2] [RFC] 64-bit io paths
Date: Fri, 23 Apr 2010 21:30:48 +0300	[thread overview]
Message-ID: <p2pf43fc5581004231130qaf3f21b3v7d9196ba58909045@mail.gmail.com> (raw)
In-Reply-To: <4BD0BD6E.4010000@twiddle.net>

On 4/23/10, Richard Henderson <rth@twiddle.net> wrote:
> On 04/22/2010 01:01 PM, Blue Swirl wrote:
>  >> This is also fine.  Although by using NULL all you'd get is a qemu
>  >>  null pointer dereference; I suppose this might get caught and
>  >>  translated to an cpu exception, but I think it would be preferable
>  >>  long-term to be more explicit about this and fill in the entries
>  >>  with a function that would explicitly raise the exception.
>  >
>  > Perhaps also the bus layer could do something here.
>
>
> What do you mean?

If we had a bus layer that handled conversion from bus width to device
width (discussed earlier), it could as well handle the cases where
instead of conversion, a bus error should be reported.

>  > Interesting. Could you make a summary of the design for the benefit of the list?
>
>
> The basic device interface looks like
>
>  +/* Object based memory region registration.  */
>  +
>  +typedef struct MemoryRegion MemoryRegion;
>  +
>  +typedef uint32_t MemoryCallbackRead(MemoryRegion *, target_phys_addr_t ofs);
>  +typedef uint64_t MemoryCallbackRead64(MemoryRegion *, target_phys_addr_t ofs);
>  +typedef void MemoryCallbackWrite(MemoryRegion *, target_phys_addr_t ofs,
>  +                                 uint32_t val);
>  +typedef void MemoryCallbackWrite64(MemoryRegion *, target_phys_addr_t ofs,
>  +                                   uint64_t val);
>  +
>  +typedef struct MemoryCallbackInfo {
>  +    MemoryCallbackRead *read8;
>  +    MemoryCallbackRead *read16;
>  +    MemoryCallbackRead *read32;
>  +    MemoryCallbackRead64 *read64;
>  +
>  +    MemoryCallbackWrite *write8;
>  +    MemoryCallbackWrite *write16;
>  +    MemoryCallbackWrite *write32;
>  +    MemoryCallbackWrite64 *write64;
>  +
>  +    /* This describes RAM.  The callbacks above need not be used, and
>  +       the host memory backing the RAM begins at qemu_get_ram_ptr_r.  */
>  +    _Bool ram;
>  +
>  +    /* Legacy shim: propagate the IO_MEM_ROMD bit.  */
>  +    _Bool romd;
>  +} MemoryCallbackInfo;
>  +
>  +/* This structure describes the region.  It is logically opaque -- drivers
>  +   should not be peeking inside.  But in the interest of efficiency we want
>  +   to directly embed this structure in the driver's private strucure.  In
>  +   this way we can avoid having to have an extra table of opaque pointers
>  +   for consumption by the driver.  The intended use is
>  +
>  +    struct FooDeviceState {
>  +        DeviceState qdev;
>  +        MemoryRegion mem_region;
>  +        ...
>  +    };
>  +
>  +    static uint32_t foo_read8(MemoryRegion *region, target_phys_addr_t ofs)
>  +    {
>  +        FooDeviceState *s = container_of(region, FooDeviceState, mem_region);
>  +        ...
>  +    }
>  +*/
>  +
>  +struct MemoryRegion {
>  +    const MemoryCallbackInfo *cb;
>  +    target_phys_addr_t start;
>  +    target_phys_addr_t size;
>  +
>  +    /* If this value is not -1, this memory region is registred in
>  +       the io_mem_region array, used by softmmu_header.h to resolve
>  +       memory-mapped operations in the guest address space.  */
>  +    int io_index;
>  +};
>  +
>  +/* Register a memory region at START_ADDR/SIZE.  The REGION structure will
>  +   be initialized appropriately for DEV using CB as the operation set.  */
>  +extern void cpu_register_memory_region(MemoryRegion *region,
>  +                                       const MemoryCallbackInfo *cb,
>  +                                       target_phys_addr_t start_addr,
>  +                                       target_phys_addr_t size);
>  +
>  +/* Unregister a memory region.  */
>  +extern void cpu_unregister_memory_region(MemoryRegion *);
>  +
>  +/* Allocate ram for use with cpu_register_memory_region.  */
>  +extern const MemoryCallbackInfo *qemu_ram_alloc_r(ram_addr_t);
>  +extern void qemu_ram_free_r(const MemoryCallbackInfo *);
>
>  The Basic Idea is that we have a MemoryRegion object that describes
>  a contiguous mapping within the guest address space.  This object
>  needs to handle RAM, ROM and devices.  The desire to handle memory
>  and devices the same comes from the wish to have PCI device BARs
>  show up as plain memory in the TLB as plain memory, and to be able
>  to handle all PCI device regions identically within sysbus.
>
>  There are a number of restrictions on the interface above what we
>  currently support:
>
>   * Objects may not be mapped over the top of existing objects.
>     This is most abused by pflash devices with their IO_MEM_ROMD thing.

Perhaps with small changes we could make this design stackable, so
that a device providing a bus inside another bus could use the same
registration functions, only the bus handle would change. Like:

upa = bus_register_memory_region(cpu_bus,,);
pci = bus_register_memory_region(upa,,);
ebus = bus_register_memory_region(pci,,):
ide = bus_register_memory_region(ebus,,):

Currently "cpu_bus" is always implicit and pci has separate
registration functions.

I'd suppose that ROMD, subpages and unassigned memory handlers could
be implemented by stacking instead of special casing them.

>   * Objects must be unmapped explicitly, rather than mapping
>     IO_MEM_UNASSIGNED over the top of an object.  This is most
>     abused by the PCI subsystem.
>
>  The use of the MemoryRegion pointer doubling as the device's opaque
>  pointer means that it's easy to implement generic helpers such as
>
>  uint64_t composite_read64(MemoryRegion *region, target_phys_addr_t ofs)
>  {
>    uint32_t v1 = region->cb->read32(region, ofs);
>    uint32_t v2 = region->cb->read32(region, ofs + 4);
>
>    return combine_for_target_endian(v1, v2);
>  }
>
>  or even
>
>  uin32_t invalid_read8(MemoryRegion *region, target_phys_addr_t ofs)
>  {
>     do_unassigned_access(region->start + ofs, 0, 0, 0, 1);
>     return 0;
>  }
>
>  without having to have supplementary opaque pointer caches, as we
>  currently do for e.g. subpage_t.
>
>  These can be entered into the device's MemoryCallbackInfo structure
>  so that we're sure that there's defined semantics for every access,
>  and the device need not invent its own invalid_read functions as
>  quite a few do now.
>
>  I will admit that I do not yet have a good replacement for IO_MEM_ROMD,
>  or toggling the read-only bit on a RAM region.  Or even for the way
>  that pc.c allocates RAM around the 640k-1M hole.

Read-only bit could be implemented in the stackable design by creating
a simple bus which can suppress writes when configured so, The device
behind would be just RAM.

Likewise for PC RAM mapping, the memory controller provides a bus
where the addresses may be twisted as needed before passing to
underlying RAM.

However, the outcome of the Generic DMA discussions (last year?) was
that instead of read/write functions, a mapping API would be better
because then we have the possibility to do zero copy DMA. Perhaps the
same applies here, too. This would be a bigger change obviously but if
there will be widespread changes to devices, it would be nice to get
this right.

  reply	other threads:[~2010-04-23 18:30 UTC|newest]

Thread overview: 19+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2010-04-20 20:26 [Qemu-devel] [PATCH 0/2] [RFC] 64-bit io paths Richard Henderson
2010-04-20 19:54 ` [Qemu-devel] [PATCH 1/2] io: Add CPUIOMemoryOps and use it Richard Henderson
2010-04-20 20:22 ` [Qemu-devel] [PATCH 2/2] io: Add readq/writeq hooks and use them Richard Henderson
2010-04-22 19:38 ` [Qemu-devel] [PATCH 0/2] [RFC] 64-bit io paths Blue Swirl
2010-04-22 19:55   ` Richard Henderson
2010-04-22 20:01     ` Blue Swirl
2010-04-22 21:19       ` Richard Henderson
2010-04-23 18:30         ` Blue Swirl [this message]
2010-05-28 20:45         ` Paul Brook
2010-04-22 23:47     ` [Qemu-devel] [PATCH] Remove IO_MEM_SUBWIDTH Richard Henderson
2010-04-25 15:06       ` [Qemu-devel] " Blue Swirl
2010-04-26 21:54         ` Artyom Tarasenko
2010-04-27 18:30           ` Richard Henderson
2010-04-28 19:29             ` Artyom Tarasenko
2010-05-06 20:25               ` Artyom Tarasenko
2010-05-07 15:28                 ` Blue Swirl
2010-05-07 16:52                   ` [Qemu-devel] [PATCH] Fill in unassigned mem read/write callbacks Richard Henderson
2010-05-07 17:02                     ` [Qemu-devel] " Blue Swirl
  -- strict thread matches above, loose matches on Subject: below --
2010-05-28 21:03 [Qemu-devel] [PATCH 0/2] [RFC] 64-bit io paths Paul Brook

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=p2pf43fc5581004231130qaf3f21b3v7d9196ba58909045@mail.gmail.com \
    --to=blauwirbel@gmail.com \
    --cc=agraf@suse.de \
    --cc=paul@codesourcery.com \
    --cc=qemu-devel@nongnu.org \
    --cc=rth@twiddle.net \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).