On 30/04/12 09:41, Avi Kivity wrote:

Yes.  I think it's even possible to do this now, you can create an mmio
region for the bus and add subregions to it.  All subregions
automatically overlap the container region.

Simply replace

   memory_region_init(&bus->address_space, ...)
   memory_region_add_subregion(&bus->address_space, addr,&dev->mmio)


   memory_region_init_io(&bus->address_space,&bus_nodev_ops, bus, ...)
   memory_region_add_subregion(&bus->address_space, addr,&dev->mmio) //

This was never used so it hasn't been tested, but the code was written
with it in mind.  I didn't want to document this so we could back out of
it, but if it's useful, let's use it.

Hi Avi,

Well I've attempted to code something like this, but I've hit a problem with devices that aren't just used by SPARC, such as the disk controller - it seems that the sysbus API can only MMIO map devices into the "root" MemoryRegion :(

The SBUS I am trying to model is actually attached to the physical address bus, but effectively the top 4 bits of the address control the multiplexing of the on-board RAM and the individual per-slot address lines. Effectively what I'm trying to model based on a 128MB default memory setting is something like this:

0x000000000 - 0x007ffffff - Normal RAM

  0x20000000 - 0x02fffffff - SBus Slot 0
  0x30000000 - 0x03fffffff - SBus Slot 1
  0x40000000 - 0x04fffffff - SBus Slot 2
  0x50000000 - 0x05fffffff - SBus Slot 3
    0x50200000 - 0x5020000f - TCX DAC
    0x50300000 - 0x5030081b - TCH THC8
    0x50301000 - 0x50301fff - TCX THC24
    0x50700000 - 0x50700fff - TCX TEC

  0x600000000 - 0x06fffffff - SBus Slot 4
  0x700000000 - 0x07fffffff - SBus Slot 5

Using your example above, I believe I can create a simple memory hierarchy to represent this and catch unknown operations in a bus_nodev_ops section no problem. The issue is that several shared peripherals such as ESP have the following in their init function:

void esp_init(target_phys_addr_t espaddr, int it_shift,
              ESPDMAMemoryReadWriteFunc dma_memory_read,
              ESPDMAMemoryReadWriteFunc dma_memory_write,
              void *dma_opaque, qemu_irq irq, qemu_irq *reset,
              qemu_irq *dma_enable)
    sysbus_mmio_map(s, 0, espaddr);

and sysbus_mmio_map() looks like this:

void sysbus_mmio_map(SysBusDevice *dev, int n, target_phys_addr_t addr)

My understanding based upon this is that it would be impossible to register a different parent MemoryRegion without duplicating the init function for all shared devices which seems undesirable :(

The only solution I can think of is to make sysbus_mmio_map() more intelligent so that instead of blindly adding the device to the "root" MemoryRegion, it traverses down the MemoryRegion hierarchy starting from the root to the furtherest leaf node it can find based upon the specified address and then adds the new subregion there. Hence if I add my SBus memory regions first before call the various peripheral init functions, everything should end up in the correct part of the memory tree.

I believe this should preserve compatibility for existing sysbus API users with just a single "root" MemoryRegion, however due to lack of any documentation related to sysbus I'm not sure if this would break other platforms or maybe even violate one of its key design features?



Reply via email to