From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:39177) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ZFf6Q-00073k-MH for qemu-devel@nongnu.org; Thu, 16 Jul 2015 05:05:15 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ZFf6N-0006cJ-3N for qemu-devel@nongnu.org; Thu, 16 Jul 2015 05:05:14 -0400 Received: from mail-wg0-x230.google.com ([2a00:1450:400c:c00::230]:34168) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ZFf6M-0006c5-Sl for qemu-devel@nongnu.org; Thu, 16 Jul 2015 05:05:11 -0400 Received: by wgkl9 with SMTP id l9so52912404wgk.1 for ; Thu, 16 Jul 2015 02:05:09 -0700 (PDT) Sender: Paolo Bonzini References: <1437035704-11299-1-git-send-email-real@ispras.ru> <1437035704-11299-4-git-send-email-real@ispras.ru> From: Paolo Bonzini Message-ID: <55A773C1.6060400@redhat.com> Date: Thu, 16 Jul 2015 11:05:05 +0200 MIME-Version: 1.0 In-Reply-To: <1437035704-11299-4-git-send-email-real@ispras.ru> Content-Type: text/plain; charset=windows-1252 Content-Transfer-Encoding: 7bit Subject: Re: [Qemu-devel] [PATCH 3/3] PAM: make PAM emulation closer to documentation List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: Efimov Vasily , qemu-devel@nongnu.org Cc: "Michael S. Tsirkin" , Kirill Batuzov On 16/07/2015 10:35, Efimov Vasily wrote: > This patch improves PAM emulation. > > PAM defines 4 memory access redirection modes. In mode 1 reads are directed to > RAM and writes are directed to PCI. In mode 2 it is contrary. In mode 0 all > access is directed to PCI. In mode 3 it is directed to RAM. Modes 0 and 3 are > well emulated but modes 1 and 2 are not. The cause is: aliases are used > while more complicated logic is required. > > The idea is to use ROM device like memory regions for mode 1 and 2 emulation > instead of aliases. Writes are directed to proper destination region by > specified I/O callback. Read redirection depends on type of source region. > In most cases source region is RAM (or ROM), so ram_addr of PAM region is set to > ram_addr of source region with offset. Otherwise, when source region is an I/O > region, reading is redirected to source region read callback by PAM region one. > > Read source and write destination regions are updated by the memory > commit callback. > > Note that we cannot use I/O region for PAM as it will violate "trying to execute > code outside RAM or ROM" assertion. > > Signed-off-by: Efimov Vasily > --- > hw/pci-host/pam.c | 238 +++++++++++++++++++++++++++++++++++++++++----- > include/hw/pci-host/pam.h | 10 +- > 2 files changed, 223 insertions(+), 25 deletions(-) > > diff --git a/hw/pci-host/pam.c b/hw/pci-host/pam.c > index 17d826c..9729b2b 100644 > --- a/hw/pci-host/pam.c > +++ b/hw/pci-host/pam.c > @@ -27,43 +27,233 @@ > * THE SOFTWARE. > */ > > -#include "qom/object.h" > -#include "sysemu/sysemu.h" > #include "hw/pci-host/pam.h" > +#include "exec/address-spaces.h" > +#include "exec/memory-internal.h" > +#include "qemu/bswap.h" > + > +static void pam_write(void *opaque, hwaddr addr, uint64_t data, > + unsigned size) > +{ > + PAMMemoryRegion *pam = (PAMMemoryRegion *) opaque; > + void *ptr; > + > + /* Destination region can be both RAM and IO. */ > + if (!memory_access_is_direct(pam->mr_write_to, true)) { > + memory_region_dispatch_write(pam->mr_write_to, > + addr + pam->write_offset, data, size, > + MEMTXATTRS_UNSPECIFIED); > + } else { > + ptr = memory_region_get_ram_ptr(pam->mr_write_to) + addr > + + pam->write_offset; > + > + switch (size) { > + case 1: > + stb_p(ptr, data); > + break; > + case 2: > + stw_he_p(ptr, data); > + break; > + case 4: > + stl_he_p(ptr, data); > + break; > + case 8: > + stq_he_p(ptr, data); > + break; > + default: > + abort(); > + } > + > + invalidate_and_set_dirty(pam->mr_write_to, addr + pam->pam_offset, > + size); > + } > +} > + The idea is very good, but the implementation relies on copying a lot of code from exec.c. Could you use an IOMMU memory region instead? Then a single region can be used to implement all four modes, and you don't hit the "trying to execute code outside RAM or RAM". Paolo