prep: improve Raven PCI host emulation
v2 cover prep: improve Raven PCI host emulation
This patchset improves Raven PCI host emulation, found in some PPC platforms, like the QEMU 'prep' one, and for example the IBM RS/6000 40p.
Some features added to raven emulation were already present in prep board (non contiguous I/O, firmware loading), while some other are new (PCI bus mastering memory region).
This patchset has been tested against Linux 2.4 PPC and IBM RS/6000 40p firmware.
Notable achievements are PCI bus mastering (tested with lsi53c895a SCSI adapter), lots of cleanup and emulation correctness, and also documentation of current hacks required by Open Hack'Ware.
This gives us a good base to replace OpenHack'Ware by a possible upcoming OpenBIOS release.
Changes since v1:
- reworked a dubious memcpy to make it work on big endian hosts
- split onto multiple patches
Hervé Poussineau (10):
prep: kill get_system_io() usage
raven: use constant PCI_NUM_PINS instead of 4
raven: move BIOS loading from board code to PCI host
raven: rename intack region to pci_intack
raven: set a correct PCI I/O memory region
raven: set a correct PCI memory region
raven: add PCI bus mastering address space
raven: implement non-contiguous I/O region
raven: fix PCI bus accesses with size > 1
raven: use raven_ for all function prefixes
hw/pci-host/prep.c | 235 ++++++++++++++++++++++++++++++++++++++++++++-------- hw/ppc/prep.c | 155 ++++++---------------------------- 2 files changed, 226 insertions(+), 164 deletions(-)
Signature · 1 line
1.7.10.4
PATCH v2 1/10 prep: kill get_system_io() usage
While ISA address space in prep machine is currently the one returned by get_system_io(), this depends of the implementation of i82378/raven devices, and this may not be the case forever.
Use the right ISA address space when adding some more ports to it. We can use whatever ISA device on the right ISA bus, as all ISA devices on the same ISA bus share the same ISA address space.
--- hw/ppc/prep.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
hw/ppc/prep.c +1 -1
@@ -656,7 +656,7 @@ static void ppc_prep_init(QEMUMachineInitArgs *args) sysctrl->reset_irq = cpu->env.irq_inputs[PPC6xx_INPUT_HRESET];portio_list_init (port_list,NULL , prep_portio_list, sysctrl,"prep" ); -portio_list_add (port_list,get_system_io (),0x0 ); +portio_list_add (port_list,isa_address_space_io (isa),0x0 );/* PowerPC control and status register group */ #if 0
Signature · 1 line
1.7.10.4
Re: [Qemu-devel] [PATCH v2 01/10] prep: kill get_system_io() usage
Il 04/09/2013 00:29, Hervé Poussineau ha scritto:
Quoted 19 lines
While ISA address space in prep machine is currently the one returned by
get_system_io(), this depends of the implementation of i82378/raven devices, and this may not be the case forever.Use the right ISA address space when adding some more ports to it. We can use whatever ISA device on the right ISA bus, as all ISA devices on the same ISA bus share the same ISA address space.
Signed-off-by Hervé Poussineau <[email protected]>--- hw/ppc/prep.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)hw/ppc/prep.c +0
-0
hw/ppc/prep.c static void ppc_prep_init(QEMUMachineInitArgs *args) · line 662
Quoted 8 lines
hw/ppc/prep.c +1
-1@@ -656,7 +656,7 @@ static void ppc_prep_init(QEMUMachineInitArgs *args) sysctrl->reset_irq = cpu->env.irq_inputs[PPC6xx_INPUT_HRESET];portio_list_init (port_list,NULL , prep_portio_list, sysctrl,"prep" ); -portio_list_add (port_list,get_system_io (),0x0 ); +portio_list_add (port_list,isa_address_space_io (isa),0x0 );/* PowerPC control and status register group */ #if 0
Should it be instead the I/O address space of the Raven instead (pci_bus->address_space_io, or alternatively you could add a new function)? Or if you make it the ISA address space, should this be a new, full-blown ISA device?
Paolo
Re: [Qemu-devel] [PATCH v2 01/10] prep: kill get_system_io() usage
Quoted 25 lines · Paolo Bonzini
Il 04/09/2013 00:29, Hervé Poussineau ha scritto:
Quoted 24 lines
While ISA address space in prep machine is currently the one returned by
get_system_io(), this depends of the implementation of i82378/raven devices, and this may not be the case forever.Use the right ISA address space when adding some more ports to it. We can use whatever ISA device on the right ISA bus, as all ISA devices on the same ISA bus share the same ISA address space.
Signed-off-by Hervé Poussineau <[email protected]>--- hw/ppc/prep.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)hw/ppc/prep.c +1
-1@@ -656,7 +656,7 @@ static void ppc_prep_init(QEMUMachineInitArgs *args) sysctrl->reset_irq = cpu->env.irq_inputs[PPC6xx_INPUT_HRESET];portio_list_init (port_list,NULL , prep_portio_list, sysctrl,"prep" ); -portio_list_add (port_list,get_system_io (),0x0 ); +portio_list_add (port_list,isa_address_space_io (isa),0x0 );
Quoted 8 lines
hw/ppc/prep.c static void ppc_prep_init(QEMUMachineInitArgs *args) · line 662
Quoted 3 lines
hw/ppc/prep.c +0
-0/* PowerPC control and status register group */ #if 0 Should it be instead the I/O address space of the Raven instead (
pci_bus->address_space_io, or alternatively you could add a new function)? Or if you make it the ISA address space, should this be a new, full-blown ISA device?
Yes, this should be replaced by a full-blow ISA device. However, this patchset is for the raven PCI host, so I tried to do only minimal and required changes in other parts.
Regards,
Hervé
PATCH v2 2/10 raven: use constant PCI_NUM_PINS instead of 4
In reply to Hervé Poussineau--- hw/pci-host/prep.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
hw/pci-host/prep.c +3 -3
@@ -47,7 +47,7 @@ typedef struct PRePPCIState {PCIHostState parent_obj;MemoryRegion intack; -qemu_irq irq[4 ]; +qemu_irq irq[PCI_NUM_PINS ];PCIBus pci_bus;RavenPCIState pci_dev; } PREPPCIState;
@@ -121,11 +121,11 @@ static void raven_pcihost_realizefn(DeviceState *d, Error **errp) isa_mem_base =0xc0000000 ; -for (i =0 ; i <4 ; i++) { +for (i =0 ; i <PCI_NUM_PINS ; i++) {sysbus_init_irq (dev, &s->irq[i]); } -pci_bus_irqs (&s->pci_bus, prep_set_irq, prep_map_irq, s->irq,4 ); +pci_bus_irqs (&s->pci_bus, prep_set_irq, prep_map_irq, s->irq,PCI_NUM_PINS );memory_region_init_io (&h->conf_mem,OBJECT (h), &pci_host_conf_be_ops, s,"pci-conf-idx" ,1 );
Signature · 1 line
1.7.10.4
PATCH v2 3/10 raven: move BIOS loading from board code to PCI host
In reply to Hervé PoussineauRaven datasheet explains where firmware lives in system memory, so do it there instead of in board code. Other boards using the same PCI host will not have to copy the firmware loading code.
However, add a specific hack for Open Hack'Ware, which provides only a 512KB blob to be loaded at 0xfff00000, but expects valid code at 0xfffffffc (specific Open Hack'Ware reset instruction pointer).
--- hw/pci-host/prep.c | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++ hw/ppc/prep.c | 50 +++++++++++++------------------------------------- 2 files changed, 64 insertions(+), 37 deletions(-)
hw/pci-host/prep.c +51 -0
@@ -28,7 +28,9 @@#include "hw/pci/pci_bus.h" #include "hw/pci/pci_host.h" #include "hw/i386/pc.h" +#include "hw/loader.h" #include "exec/address-spaces.h" +#include "elf.h" #define TYPE_RAVEN_PCI_DEVICE "raven"#define TYPE_RAVEN_PCI_HOST_BRIDGE "raven-pcihost"
@@ -38,6 +40,9 @@typedef struct RavenPCIState {PCIDevice dev; +uint32_t elf_machine; +char *bios_name; +MemoryRegion bios; }RavenPCIState ;#define RAVEN_PCI_HOST_BRIDGE (obj) \
@@ -52,6 +57,8 @@ typedef struct PRePPCIState {RavenPCIState pci_dev; } PREPPCIState; +#define BIOS_SIZE (1024 * 1024) +static inline uint32_t PPC_PCIIO_config (hwaddr addr) {int i;
@@ -169,10 +176,46 @@ static void raven_pcihost_initfn(Object *obj)static int raven_init (PCIDevice *d) { +Object *obj =OBJECT (d); +RavenPCIState *s =RAVEN_PCI_DEVICE (d); +char *filename; +int bios_size =-1 ; + d->config[0x0C ] =0x08 ;// cache_line_size d->config[0x0D ] =0x10 ;// latency_timer d->config[0x34 ] =0x00 ;// capabilities_pointer +memory_region_init_ram (&s->bios, obj,"bios" ,BIOS_SIZE ); +memory_region_set_readonly (&s->bios, true); +memory_region_add_subregion (get_system_memory (), (uint32_t )(-BIOS_SIZE ), + &s->bios); +vmstate_register_ram_global (&s->bios); +if (s->bios_name) { + filename =qemu_find_file (QEMU_FILE_TYPE_BIOS , s->bios_name); +if (filename) { +if (s->elf_machine !=EM_NONE ) { + bios_size =load_elf (filename,NULL ,NULL ,NULL , +NULL ,NULL ,1 , s->elf_machine,0 ); + } +if (bios_size <0 ) { + bios_size =get_image_size (filename); +if (bios_size >0 && bios_size <=BIOS_SIZE ) { +hwaddr bios_addr; + bios_size = (bios_size +0xfff ) & ~0xfff ; + bios_addr = (uint32_t )(-BIOS_SIZE ); + bios_size =load_image_targphys (filename, bios_addr, + bios_size); + } + } + } +if (bios_size <0 || bios_size >BIOS_SIZE ) { +hw_error ("qemu: could not load bios image '%s'\n" , s->bios_name); + } +if (filename) { +g_free (filename); + } + } +return 0 ; }
@@ -208,12 +251,20 @@ static const TypeInfo raven_info = { .class_init = raven_class_init, }; +static Property raven_pcihost_properties[] = { +DEFINE_PROP_UINT32 ("elf-machine" , PREPPCIState, pci_dev.elf_machine, +EM_NONE ), +DEFINE_PROP_STRING ("bios-name" , PREPPCIState, pci_dev.bios_name), +DEFINE_PROP_END_OF_LIST () +}; +static void raven_pcihost_class_init (ObjectClass *klass,void *data) {DeviceClass *dc =DEVICE_CLASS (klass);set_bit (DEVICE_CATEGORY_BRIDGE , dc->categories); dc->realize = raven_pcihost_realizefn; + dc->props = raven_pcihost_properties; dc->fw_name ="pci" ; dc->no_user =1 ; }
hw/ppc/prep.c +13 -37
74 lines not on this page · raw message
Signature · 1 line
1.7.10.4
PATCH v2 4/10 raven: rename intack region to pci_intack
In reply to Hervé PoussineauRegions added in next patches will also have the pci_ prefix.
--- hw/pci-host/prep.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-)
hw/pci-host/prep.c +4 -3
@@ -51,9 +51,9 @@ typedef struct RavenPCIState {typedef struct PRePPCIState {PCIHostState parent_obj; -MemoryRegion intack;qemu_irq irq[PCI_NUM_PINS ];PCIBus pci_bus; +MemoryRegion pci_intack;RavenPCIState pci_dev; }PREPPCIState ;
@@ -147,8 +147,9 @@ static void raven_pcihost_realizefn(DeviceState *d, Error **errp)memory_region_init_io (&h->mmcfg,OBJECT (s), &PPC_PCIIO_ops, s,"pciio" ,0x00400000 );memory_region_add_subregion (address_space_mem,0x80800000 , &h->mmcfg); -memory_region_init_io (&s->intack,OBJECT (s), &PPC_intack_ops, s,"pci-intack" ,1 ); -memory_region_add_subregion (address_space_mem,0xbffffff0 , &s->intack); +memory_region_init_io (&s->pci_intack,OBJECT (s), &PPC_intack_ops, s, +"pci-intack" ,1 ); +memory_region_add_subregion (address_space_mem,0xbffffff0 , &s->pci_intack);/* TODO Remove once realize propagates to child devices. */ object_property_set_bool (OBJECT (&s->pci_dev), true,"realized" , errp);
Signature · 1 line
1.7.10.4
PATCH v2 5/10 raven: set a correct PCI I/O memory region
In reply to Hervé PoussineauPCI I/O region is 0x3f800000 bytes starting at 0x80000000. Do not use global QEMU I/O region, which is only 64KB.
--- hw/pci-host/prep.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-)
hw/pci-host/prep.c +9 -6
@@ -53,6 +53,7 @@ typedef struct PRePPCIState {qemu_irq irq[PCI_NUM_PINS ];PCIBus pci_bus; +MemoryRegion pci_io;MemoryRegion pci_intack;RavenPCIState pci_dev; } PREPPCIState;
@@ -136,13 +137,11 @@ static void raven_pcihost_realizefn(DeviceState *d, Error **errp)memory_region_init_io (&h->conf_mem,OBJECT (h), &pci_host_conf_be_ops, s,"pci-conf-idx" ,1 ); -sysbus_add_io (dev,0xcf8 , &h->conf_mem); -sysbus_init_ioports (&h->busdev,0xcf8 ,1 ); +memory_region_add_subregion (&s->pci_io,0xcf8 , &h->conf_mem);memory_region_init_io (&h->data_mem,OBJECT (h), &pci_host_data_be_ops, s,"pci-conf-data" ,1 ); -sysbus_add_io (dev,0xcfc , &h->data_mem); -sysbus_init_ioports (&h->busdev,0xcfc ,1 ); +memory_region_add_subregion (&s->pci_io,0xcfc , &h->data_mem);memory_region_init_io (&h->mmcfg,OBJECT (s), &PPC_PCIIO_ops, s,"pciio" ,0x00400000 );memory_region_add_subregion (address_space_mem,0x80800000 , &h->mmcfg);
@@ -160,11 +159,15 @@ static void raven_pcihost_initfn(Object *obj)PCIHostState *h =PCI_HOST_BRIDGE (obj);PREPPCIState *s =RAVEN_PCI_HOST_BRIDGE (obj);MemoryRegion *address_space_mem =get_system_memory (); -MemoryRegion *address_space_io =get_system_io ();DeviceState *pci_dev; +memory_region_init (&s->pci_io, obj,"pci-io" ,0x3f800000 ); + +/* CPU address space */ +memory_region_add_subregion (address_space_mem,0x80000000 , &s->pci_io);pci_bus_new_inplace (&s->pci_bus,DEVICE (obj),NULL , - address_space_mem, address_space_io,0 ,TYPE_PCI_BUS ); + address_space_mem, &s->pci_io,0 ,TYPE_PCI_BUS ); + h->bus = &s->pci_bus;object_initialize (&s->pci_dev,TYPE_RAVEN_PCI_DEVICE );
Signature · 1 line
1.7.10.4
Re: [Qemu-devel] [PATCH v2 05/10] raven: set a correct PCI I/O memory region
Il 04/09/2013 00:29, Hervé Poussineau ha scritto:
Quoted 2 lines
PCI I/O region is
0x3f800000bytes starting at0x80000000. Do not use global QEMU I/O region, which is only 64KB.
You can make the global QEMU I/O region larger, that's not a problem.
Not using address_space_io is fine as well, but it's a separate change and I doubt it is a good idea to do it for a single target; if you do it for all non-x86 PCI bridges, and move the initialization of address_space_io to target-i386, that's a different story of course.
Paolo
Quoted 52 lines
Signed-off-by Hervé Poussineau <[email protected]>--- hw/pci-host/prep.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-)hw/pci-host/prep.c +9
-6@@ -53,6 +53,7 @@ typedef struct PRePPCIState {qemu_irq irq[PCI_NUM_PINS ];PCIBus pci_bus; +MemoryRegion pci_io;MemoryRegion pci_intack;RavenPCIState pci_dev; } PREPPCIState;@@ -136,13 +137,11 @@ static void raven_pcihost_realizefn(DeviceState *d, Error **errp)memory_region_init_io (&h->conf_mem,OBJECT (h), &pci_host_conf_be_ops, s,"pci-conf-idx" ,1 ); -sysbus_add_io (dev,0xcf8 , &h->conf_mem); -sysbus_init_ioports (&h->busdev,0xcf8 ,1 ); +memory_region_add_subregion (&s->pci_io,0xcf8 , &h->conf_mem);memory_region_init_io (&h->data_mem,OBJECT (h), &pci_host_data_be_ops, s,"pci-conf-data" ,1 ); -sysbus_add_io (dev,0xcfc , &h->data_mem); -sysbus_init_ioports (&h->busdev,0xcfc ,1 ); +memory_region_add_subregion (&s->pci_io,0xcfc , &h->data_mem);memory_region_init_io (&h->mmcfg,OBJECT (s), &PPC_PCIIO_ops, s,"pciio" ,0x00400000 );memory_region_add_subregion (address_space_mem,0x80800000 , &h->mmcfg);@@ -160,11 +159,15 @@ static void raven_pcihost_initfn(Object *obj)PCIHostState *h =PCI_HOST_BRIDGE (obj);PREPPCIState *s =RAVEN_PCI_HOST_BRIDGE (obj);MemoryRegion *address_space_mem =get_system_memory (); -MemoryRegion *address_space_io =get_system_io ();DeviceState *pci_dev; +memory_region_init (&s->pci_io, obj,"pci-io" ,0x3f800000 ); + +/* CPU address space */ +memory_region_add_subregion (address_space_mem,0x80000000 , &s->pci_io);pci_bus_new_inplace (&s->pci_bus,DEVICE (obj),NULL , - address_space_mem, address_space_io,0 ,TYPE_PCI_BUS ); + address_space_mem, &s->pci_io,0 ,TYPE_PCI_BUS ); + h->bus = &s->pci_bus;object_initialize (&s->pci_dev,TYPE_RAVEN_PCI_DEVICE );
Re: [Qemu-devel] [PATCH v2 05/10] raven: set a correct PCI I/O memory region
Quoted 4 lines · Paolo Bonzini
Not using
address_space_iois fine as well, but it's a separate change and I doubt it is a good idea to do it for a single target; if you do it for all non-x86 PCI bridges, and move the initialization ofaddress_space_ioto target-i386, that's a different story of course.
What's the problem with doing it for a single target? That's what I did for versatilepb. I think any CPU that doesn't have inb/outb type instructions (x86 does, and I think also alpha but I forget) should not be using address_space_io; but the easiest way to get there is to convert the PCI bridges one at a time as we have maintenance effort to do so.
-- PMM
Re: [Qemu-devel] [PATCH v2 05/10] raven: set a correct PCI I/O memory region
Il 04/09/2013 09:22, Peter Maydell ha scritto:
Quoted 8 lines
Quoted 4 lines
Not using
address_space_iois fine as well, but it's a separate change and I doubt it is a good idea to do it for a single target; if you do it for all non-x86 PCI bridges, and move the initialization ofaddress_space_ioto target-i386, that's a different story of course.What's the problem with doing it for a single target? That's what I did for versatilepb. I think any CPU that doesn't have inb/outb type instructions (x86 does, and I think also alpha but I forget)
Actually, Alpha is also not using address_space_io at all as far as I can see.
Quoted 3 lines
should not be using
address_space_io; but the easiest way to get there is to convert the PCI bridges one at a time as we have maintenance effort to do so.
I'm not against the patch, but there are less than ten host bridges and most of them should be tested by "make check", so I would prefer to have a plan for making things consistent.
Paolo
Re: [Qemu-devel] [PATCH v2 05/10] raven: set a correct PCI I/O memory region
Quoted 8 lines · Paolo Bonzini
Il 04/09/2013 09:22, Peter Maydell ha scritto:
Quoted 3 lines
should not be using
address_space_io; but the easiest way to get there is to convert the PCI bridges one at a time as we have maintenance effort to do so.I'm not against the patch, but there are less than ten host bridges and most of them should be tested by "make check", so I would prefer to have a plan for making things consistent.
My plan for that goes:
1. where people are overhauling a host bridge (ie in a patchset like this one) allow them to make the changes that move in the right direction
2. look at how many other bridges remain after that
3. fix the other bridges if anybody has time and effort
(Does 'make check' really test all the host bridges? This doesn't seem very likely to me.)
-- PMM
Re: [Qemu-devel] [PATCH v2 05/10] raven: set a correct PCI I/O memory region
Il 04/09/2013 10:25, Peter Maydell ha scritto:
Quoted 9 lines
My plan for that goes:
1. where people are overhauling a host bridge (ie in a patchset like this one) allow them to make the changes that move in the right direction
2. look at how many other bridges remain after that
3. fix the other bridges if anybody has time and effort(Does 'make check' really test all the host bridges? This doesn't seem very likely to me.)
The endianness test does reads and writes to the I/O address space of most bridges.
Paolo
Re: [Qemu-devel] [PATCH v2 05/10] raven: set a correct PCI I/O memory region
Quoted 2 lines · Paolo Bonzini
The endianness test does reads and writes to the I/O address space of most bridges.
Nice. It looks like it's using an ISA device though, which is a bit of a roundabout way of testing PCI I/O (means it can't test the versatile pci bridge's handling of PCI I/O access, for instance).
-- PMM
Re: [Qemu-devel] [PATCH v2 05/10] raven: set a correct PCI I/O memory region
In reply to Peter MaydellAm 04.09.2013 10:25, schrieb Peter Maydell:
Quoted 2 lines
(Does 'make check' really test all the host bridges? This doesn't seem very likely to me.)
Not sure if all yet. Now that the ppc pull is merged, I'll respin and push forward my qom-test, which covers all targets and thereby all PHBs instantiated by default. I'm not aware of any instantiated from the command line (apart from the mac99 DEC ugliness).
Andreas
Re: [Qemu-devel] [PATCH v2 05/10] raven: set a correct PCI I/O memory region
In reply to Peter MaydellQuoted 16 lines · Peter Maydell
Quoted 7 lines · Paolo Bonzini
Il 04/09/2013 09:22, Peter Maydell ha scritto:
Quoted 3 lines
should not be using
address_space_io; but the easiest way to get there is to convert the PCI bridges one at a time as we have maintenance effort to do so.I'm not against the patch, but there are less than ten host bridges and most of them should be tested by "make check", so I would prefer to have a plan for making things consistent.
My plan for that goes:
1. where people are overhauling a host bridge (ie in a patchset like this one) allow them to make the changes that move in the right direction
2. look at how many other bridges remain after that
3. fix the other bridges if anybody has time and effort
Quoted 2 lines
(Does 'make check' really test all the host bridges? This doesn't seem very likely to me.)
Paolo, Peter, so, did we raise some consensus? Should I reuse get_system_io(), or having a separate MemoryRegion is acceptable?
I think that creating a independant MemoryRegion is better, as I see no reason why QEMU should provide a global I/O region, which has some sense mostly on x86 architectures only. However, I can rework patches to use get_system_io() if that's what you prefer...
Hervé
Re: [Qemu-devel] [PATCH v2 05/10] raven: set a correct PCI I/O memory region
Quoted 7 lines · Hervé Poussineau
Paolo, Peter, so, did we raise some consensus? Should I reuse
get_system_io(), or having a separate MemoryRegion is acceptable? I think that creating a independant MemoryRegion is better, as I see no reason why QEMU should provide a global I/O region, which has some sense mostly on x86 architectures only.
However, I can rework patches to useget_system_io()if that's what you prefer...
I don't think there's any reason to use get_system_io() here, and I don't think we need to block cleaning up this host bridge on some cleanup of every host bridge at once -- that seems unrealistic to me since nobody really has a complete understanding of every platform that would touch.
-- PMM
Re: [Qemu-devel] [PATCH v2 05/10] raven: set a correct PCI I/O memory region
In reply to Hervé PoussineauIl 09/09/2013 22:57, Hervé Poussineau ha scritto:
Quoted 9 lines
Quoted 1 line
Paolo, Peter, so, did we raise some consensus? Should I reuse
get_system_io(), or having a separate MemoryRegion is acceptable? I think that creating a independant MemoryRegion is better, as I see no reason why QEMU should provide a global I/O region, which has some sense mostly on x86 architectures only.
However, I can rework patches to useget_system_io()if that's what you prefer...
Since alpha-softmmu and versatile have established a precedent, your patch is fine.
Thanks!
Paolo
PATCH v2 6/10 raven: set a correct PCI memory region
In reply to Hervé PoussineauPCI memory region is 0x3f000000 bytes starting at 0xc0000000.
However, keep compatibility with Open Hack'Ware expectations by adding a hack for Open Hack'Ware display.
--- hw/pci-host/prep.c | 9 ++++++--- hw/ppc/prep.c | 9 +++++++++ 2 files changed, 15 insertions(+), 3 deletions(-)
hw/pci-host/prep.c +6 -3
@@ -54,6 +54,7 @@ typedef struct PRePPCIState {qemu_irq irq[PCI_NUM_PINS ];PCIBus pci_bus;MemoryRegion pci_io; +MemoryRegion pci_memory;MemoryRegion pci_intack;RavenPCIState pci_dev; } PREPPCIState;
@@ -127,8 +128,6 @@ static void raven_pcihost_realizefn(DeviceState *d, Error **errp)MemoryRegion *address_space_mem =get_system_memory ();int i; - isa_mem_base =0xc0000000 ; -for (i =0 ; i <PCI_NUM_PINS ; i++) {sysbus_init_irq (dev, &s->irq[i]); }
@@ -162,11 +161,15 @@ static void raven_pcihost_initfn(Object *obj)DeviceState *pci_dev;memory_region_init (&s->pci_io, obj,"pci-io" ,0x3f800000 ); +/* Open Hack'Ware hack: real size should be only 0x3f000000 bytes */ +memory_region_init (&s->pci_memory, obj,"pci-memory" , +0x3f000000 +0xc0000000ULL );/* CPU address space */ memory_region_add_subregion (address_space_mem,0x80000000 , &s->pci_io); +memory_region_add_subregion (address_space_mem,0xc0000000 , &s->pci_memory);pci_bus_new_inplace (&s->pci_bus,DEVICE (obj),NULL , - address_space_mem, &s->pci_io,0 ,TYPE_PCI_BUS ); + &s->pci_memory, &s->pci_io,0 ,TYPE_PCI_BUS ); h->bus = &s->pci_bus;
hw/ppc/prep.c +9 -0
@@ -466,6 +466,7 @@ static void ppc_prep_init(QEMUMachineInitArgs *args)int linux_boot, i, nb_nics1;MemoryRegion *ram =g_new (MemoryRegion,1 );MemoryRegion *bios =g_new (MemoryRegion,1 ); +MemoryRegion *vga =g_new (MemoryRegion,1 );uint32_t kernel_base, initrd_base;long kernel_size, initrd_size;DeviceState *dev;
@@ -604,6 +605,14 @@ static void ppc_prep_init(QEMUMachineInitArgs *args)/* init basic PC hardware */ pci_vga_init (pci_bus); +/* Open Hack'Ware hack: PCI BAR#0 is programmed to 0xf0000000. +* While bios will access framebuffer at 0xf0000000, real physical +* address is 0xf0000000 + 0xc0000000 (PCI memory base). +* Alias the wrong memory accesses to the right place. +*/ +memory_region_init_alias (vga,NULL ,"vga-alias" ,pci_address_space (pci), +0xf0000000 ,0x1000000 ); +memory_region_add_subregion_overlap (sysmem,0xf0000000 , vga,10 ); nb_nics1 = nb_nics;if (nb_nics1 >NE2000_NB_MAX )
Signature · 1 line
1.7.10.4
PATCH v2 7/10 raven: add PCI bus mastering address space
In reply to Hervé PoussineauThis has been tested on Linux 2.4/PPC with the lsi53c895a SCSI adapter.
--- hw/pci-host/prep.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+)
hw/pci-host/prep.c +23 -0
@@ -56,6 +56,10 @@ typedef struct PRePPCIState {MemoryRegion pci_io;MemoryRegion pci_memory;MemoryRegion pci_intack; +MemoryRegion bm; +MemoryRegion bm_ram_alias; +MemoryRegion bm_pci_memory_alias; +AddressSpace bm_as;RavenPCIState pci_dev; } PREPPCIState;
@@ -120,6 +124,13 @@ static void prep_set_irq(void *opaque, int irq_num, int level)qemu_set_irq (pic[irq_num] , level); } +static AddressSpace *raven_pcihost_set_iommu (PCIBus *bus,void *opaque, +int devfn) +{ +PREPPCIState *s = opaque; +return &s->bm_as; +} +static void raven_pcihost_realizefn (DeviceState *d,Error **errp) {SysBusDevice *dev =SYS_BUS_DEVICE (d);
@@ -171,6 +182,18 @@ static void raven_pcihost_initfn(Object *obj)pci_bus_new_inplace (&s->pci_bus,DEVICE (obj),NULL , &s->pci_memory, &s->pci_io,0 ,TYPE_PCI_BUS ); +/* Bus master address space */ +memory_region_init (&s->bm, obj,"bm-raven" ,UINT32_MAX ); +memory_region_init_alias (&s->bm_pci_memory_alias, obj,"bm-pci-memory" , + &s->pci_memory,0 , +memory_region_size (&s->pci_memory)); +memory_region_init_alias (&s->bm_ram_alias, obj,"bm-system" , +get_system_memory (),0 ,0x80000000 ); +memory_region_add_subregion (&s->bm,0 , &s->bm_pci_memory_alias); +memory_region_add_subregion (&s->bm,0x80000000 , &s->bm_ram_alias); +address_space_init (&s->bm_as, &s->bm,"raven-bm" ); +pci_setup_iommu (&s->pci_bus, raven_pcihost_set_iommu, s); + h->bus = &s->pci_bus;object_initialize (&s->pci_dev,TYPE_RAVEN_PCI_DEVICE );
Signature · 1 line
1.7.10.4
PATCH v2 8/10 raven: implement non-contiguous I/O region
In reply to Hervé PoussineauRemove now duplicated code from prep board.
--- hw/pci-host/prep.c | 82 +++++++++++++++++++++++++++++++++++++++++++++ hw/ppc/prep.c | 94 ++-------------------------------------------------- 2 files changed, 85 insertions(+), 91 deletions(-)
hw/pci-host/prep.c +82 -0
@@ -53,7 +53,9 @@ typedef struct PRePPCIState {qemu_irq irq[PCI_NUM_PINS ];PCIBus pci_bus; +AddressSpace pci_io_as;MemoryRegion pci_io; +MemoryRegion pci_io_non_contiguous;MemoryRegion pci_memory;MemoryRegion pci_intack;MemoryRegion bm;
@@ -61,6 +63,8 @@ typedef struct PRePPCIState {MemoryRegion bm_pci_memory_alias;AddressSpace bm_as;RavenPCIState pci_dev; + +int contiguous_map; } PREPPCIState;#define BIOS_SIZE (1024 * 1024)
@@ -112,6 +116,71 @@ static const MemoryRegionOps PPC_intack_ops = { }, }; +static inline hwaddr raven_io_address (PREPPCIState *s, +hwaddr addr) +{ +if (s->contiguous_map ==0 ) { +/* 64 KB contiguous space for IOs */ + addr &=0xFFFF ; + }else { +/* 8 MB non-contiguous space for IOs */ + addr = (addr &0x1F ) | ((addr &0x007FFF000 ) >>7 ); + } + +/* FIXME: handle endianness switch */ + +return addr; +} + +static uint64_t raven_io_read (void *opaque,hwaddr addr, +unsigned int size) +{ +PREPPCIState *s = opaque; +uint8_t buf[4 ]; + + addr =raven_io_address (s, addr); +address_space_read (&s->pci_io_as, addr +0x80000000 , buf, size); + +if (size ==1 ) { +return buf[0 ]; + }else if (size ==2 ) { +return lduw_p (buf); + }else if (size ==4 ) { +return ldl_p (buf); + }else { +assert (false); + } +} + +static void raven_io_write (void *opaque,hwaddr addr, +uint64_t val,unsigned int size) +{ +PREPPCIState *s = opaque; +uint8_t buf[4 ]; + + addr =raven_io_address (s, addr); + +if (size ==1 ) { + buf[0 ] = val; + }else if (size ==2 ) { +stw_p (buf, val); + }else if (size ==4 ) { +stl_p (buf, val); + }else { +assert (false); + } + +address_space_write (&s->pci_io_as, addr +0x80000000 , buf, size); +} + +static const MemoryRegionOps raven_io_ops = { + .read = raven_io_read, + .write = raven_io_write, + .endianness =DEVICE_LITTLE_ENDIAN , + .impl.max_access_size =4 , + .valid.unaligned = true, +}; +static int prep_map_irq (PCIDevice *pci_dev,int irq_num) {return (irq_num + (pci_dev->devfn >>3 )) &1 ;
@@ -131,6 +200,12 @@ static AddressSpace *raven_pcihost_set_iommu(PCIBus *bus, void *opaque,return &s->bm_as; } +static void raven_change_gpio (void *opaque,int n,int level) +{ +PREPPCIState *s = opaque; + s->contiguous_map = level; +} +static void raven_pcihost_realizefn (DeviceState *d,Error **errp) {SysBusDevice *dev =SYS_BUS_DEVICE (d);
@@ -143,6 +218,8 @@ static void raven_pcihost_realizefn(DeviceState *d, Error **errp)sysbus_init_irq (dev, &s->irq[i]); } +qdev_init_gpio_in (d, raven_change_gpio,1 ); +pci_bus_irqs (&s->pci_bus, prep_set_irq, prep_map_irq, s->irq,PCI_NUM_PINS ); memory_region_init_io(&h->conf_mem, OBJECT(h), &pci_host_conf_be_ops, s,
@@ -172,12 +249,17 @@ static void raven_pcihost_initfn(Object *obj)DeviceState *pci_dev;memory_region_init (&s->pci_io, obj,"pci-io" ,0x3f800000 ); +memory_region_init_io (&s->pci_io_non_contiguous, obj, &raven_io_ops, s, +"pci-io-non-contiguous" ,0x00800000 );/* Open Hack'Ware hack: real size should be only 0x3f000000 bytes */ memory_region_init (&s->pci_memory, obj,"pci-memory" ,0x3f000000 +0xc0000000ULL ); +address_space_init (&s->pci_io_as, &s->pci_io,"raven-io" );/* CPU address space */ memory_region_add_subregion (address_space_mem,0x80000000 , &s->pci_io); +memory_region_add_subregion_overlap (address_space_mem,0x80000000 , + &s->pci_io_non_contiguous,1 );memory_region_add_subregion (address_space_mem,0xc0000000 , &s->pci_memory);pci_bus_new_inplace (&s->pci_bus,DEVICE (obj),NULL , &s->pci_memory, &s->pci_io,0 ,TYPE_PCI_BUS );
hw/ppc/prep.c +3 -91
130 lines not on this page · raw message
Signature · 1 line
1.7.10.4
PATCH v2 9/10 raven: fix PCI bus accesses with size > 1
In reply to Hervé Poussineau--- hw/pci-host/prep.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
hw/pci-host/prep.c +4 -4
@@ -222,12 +222,12 @@ static void raven_pcihost_realizefn(DeviceState *d, Error **errp)pci_bus_irqs (&s->pci_bus, prep_set_irq, prep_map_irq, s->irq,PCI_NUM_PINS ); -memory_region_init_io (&h->conf_mem,OBJECT (h), &pci_host_conf_be_ops, s, -"pci-conf-idx" ,1 ); +memory_region_init_io (&h->conf_mem,OBJECT (h), &pci_host_conf_le_ops, s, +"pci-conf-idx" ,4 );memory_region_add_subregion (&s->pci_io,0xcf8 , &h->conf_mem); -memory_region_init_io (&h->data_mem,OBJECT (h), &pci_host_data_be_ops, s, -"pci-conf-data" ,1 ); +memory_region_init_io (&h->data_mem,OBJECT (h), &pci_host_data_le_ops, s, +"pci-conf-data" ,4 );memory_region_add_subregion (&s->pci_io,0xcfc , &h->data_mem);memory_region_init_io (&h->mmcfg,OBJECT (s), &PPC_PCIIO_ops, s,"pciio" ,0x00400000 );
Signature · 1 line
1.7.10.4
PATCH v2 10/10 raven: use raven_ for all function prefixes
In reply to Hervé Poussineau--- hw/pci-host/prep.c | 40 +++++++++++++++++++++------------------- 1 file changed, 21 insertions(+), 19 deletions(-)
hw/pci-host/prep.c +21 -19
@@ -69,7 +69,7 @@ typedef struct PRePPCIState {#define BIOS_SIZE (1024 * 1024) -static inline uint32_t PPC_PCIIO_config (hwaddr addr) +static inline uint32_t raven_pci_io_config (hwaddr addr) {int i;
@@ -81,36 +81,36 @@ static inline uint32_t PPC_PCIIO_config(hwaddr addr)return (addr &0x7ff ) | (i <<11 ); } -static void ppc_pci_io_write (void *opaque,hwaddr addr, -uint64_t val,unsigned int size) +static void raven_pci_io_write (void *opaque,hwaddr addr, +uint64_t val,unsigned int size) {PREPPCIState *s = opaque;PCIHostState *phb =PCI_HOST_BRIDGE (s); -pci_data_write (phb->bus,PPC_PCIIO_config (addr), val, size); +pci_data_write (phb->bus,raven_pci_io_config (addr), val, size); } -static uint64_t ppc_pci_io_read (void *opaque,hwaddr addr, -unsigned int size) +static uint64_t raven_pci_io_read (void *opaque,hwaddr addr, +unsigned int size) {PREPPCIState *s = opaque;PCIHostState *phb =PCI_HOST_BRIDGE (s); -return pci_data_read (phb->bus,PPC_PCIIO_config (addr), size); +return pci_data_read (phb->bus,raven_pci_io_config (addr), size); } -static const MemoryRegionOps PPC_PCIIO_ops = { - .read = ppc_pci_io_read, - .write = ppc_pci_io_write, +static const MemoryRegionOps raven_pci_io_ops = { + .read = raven_pci_io_read, + .write = raven_pci_io_write, .endianness =DEVICE_LITTLE_ENDIAN , }; -static uint64_t ppc_intack_read (void *opaque,hwaddr addr, -unsigned int size) +static uint64_t raven_intack_read (void *opaque,hwaddr addr, +unsigned int size) {return pic_read_irq (isa_pic); } -static const MemoryRegionOps PPC_intack_ops = { - .read = ppc_intack_read, +static const MemoryRegionOps raven_intack_ops = { + .read = raven_intack_read, .valid = { .max_access_size =1 , },
@@ -181,12 +181,12 @@ static const MemoryRegionOps raven_io_ops = { .valid.unaligned = true, }; -static int prep_map_irq (PCIDevice *pci_dev,int irq_num) +static int raven_map_irq (PCIDevice *pci_dev,int irq_num) {return (irq_num + (pci_dev->devfn >>3 )) &1 ; } -static void prep_set_irq (void *opaque,int irq_num,int level) +static void raven_set_irq (void *opaque,int irq_num,int level) {qemu_irq *pic = opaque;
@@ -220,7 +220,8 @@ static void raven_pcihost_realizefn(DeviceState *d, Error **errp)qdev_init_gpio_in (d, raven_change_gpio,1 ); -pci_bus_irqs (&s->pci_bus, prep_set_irq, prep_map_irq, s->irq,PCI_NUM_PINS ); +pci_bus_irqs (&s->pci_bus, raven_set_irq, raven_map_irq, s->irq, +PCI_NUM_PINS );memory_region_init_io (&h->conf_mem,OBJECT (h), &pci_host_conf_le_ops, s,"pci-conf-idx" ,4 );
@@ -230,10 +231,11 @@ static void raven_pcihost_realizefn(DeviceState *d, Error **errp) "pci-conf-data", 4);memory_region_add_subregion (&s->pci_io,0xcfc , &h->data_mem); -memory_region_init_io (&h->mmcfg,OBJECT (s), &PPC_PCIIO_ops, s,"pciio" ,0x00400000 ); +memory_region_init_io (&h->mmcfg,OBJECT (s), &raven_pci_io_ops, s, +"pciio" ,0x00400000 );memory_region_add_subregion (address_space_mem,0x80800000 , &h->mmcfg); -memory_region_init_io (&s->pci_intack,OBJECT (s), &PPC_intack_ops, s, +memory_region_init_io (&s->pci_intack,OBJECT (s), &raven_intack_ops, s,"pci-intack" ,1 );memory_region_add_subregion (address_space_mem,0xbffffff0 , &s->pci_intack);
Signature · 1 line
1.7.10.4