1. 11 9月, 2015 3 次提交
    • K
      xen/pt: Check if reg->init function sets the 'data' past the reg->size · 5b4dd0f5
      Konrad Rzeszutek Wilk 提交于
      It should never happen, but in case it does (an developer adds
      a new register and the 'init_val' expands past the register
      size) we want to report. The code will only write up to
      reg->size so there is no runtime danger of the register spilling
      across other ones - however to catch this sort of thing
      we still return an error.
      Signed-off-by: NKonrad Rzeszutek Wilk <konrad.wilk@oracle.com>
      Signed-off-by: NStefano Stabellini <stefano.stabellini@eu.citrix.com>
      5b4dd0f5
    • K
      xen/pt: Sync up the dev.config and data values. · 2e87512e
      Konrad Rzeszutek Wilk 提交于
      For a passthrough device we maintain a state of emulated
      registers value contained within d->config. We also consult
      the host registers (and apply ro and write masks) whenever
      the guest access the registers. This is done in xen_pt_pci_write_config
      and xen_pt_pci_read_config.
      
      Also in this picture we call pci_default_write_config which
      updates the d->config and if the d->config[PCI_COMMAND] register
      has PCI_COMMAND_MEMORY (or PCI_COMMAND_IO) acts on those changes.
      
      On startup the d->config[PCI_COMMAND] are the host values, not
      what the guest initial values should be, which is exactly what
      we do _not_ want to do for 64-bit BARs when the guest just wants
      to read the size of the BAR. Huh you say?
      
      To get the size of 64-bit memory space BARs,  the guest has
      to calculate ((BAR[x] & 0xFFFFFFF0) + ((BAR[x+1] & 0xFFFFFFFF) << 32))
      which means it has to do two writes of ~0 to BARx and BARx+1.
      
      prior to this patch and with XSA120-addendum patch (Linux kernel)
      the PCI_COMMAND register is copied from the host it can have
      PCI_COMMAND_MEMORY bit set which means that QEMU will try to
      update the hypervisor's P2M with BARx+1 value to ~0 (0xffffffff)
      (to sync the guest state to host) instead of just having
      xen_pt_pci_write_config and xen_pt_bar_reg_write apply the
      proper masks and return the size to the guest.
      
      To thwart this, this patch syncs up the host values with the
      guest values taking into account the emu_mask (bit set means
      we emulate, PCI_COMMAND_MEMORY and PCI_COMMAND_IO are set).
      That is we copy the host values - masking out any bits which
      we will emulate. Then merge it with the initial emulation register
      values. Lastly this value is then copied both in
      dev.config _and_ XenPTReg->data field.
      
      There is also reg->size accounting taken into consideration
      that ends up being used in patch.
       xen/pt: Check if reg->init function sets the 'data' past the reg->size
      
      This fixes errors such as these:
      
      (XEN) memory_map:add: dom2 gfn=fffe0 mfn=fbce0 nr=20
      (DEBUG) 189 pci dev 04:0 BAR16 wrote ~0.
      (DEBUG) 200 pci dev 04:0 BAR16 read 0x0fffe0004.
      (XEN) memory_map:remove: dom2 gfn=fffe0 mfn=fbce0 nr=20
      (DEBUG) 204 pci dev 04:0 BAR16 wrote 0x0fffe0004.
      (DEBUG) 217 pci dev 04:0 BAR16 read upper 0x000000000.
      (XEN) memory_map:add: dom2 gfn=ffffffff00000 mfn=fbce0 nr=20
      (XEN) p2m.c:883:d0v0 p2m_set_entry failed! mfn=ffffffffffffffff rc:-22
      (XEN) memory_map:fail: dom2 gfn=ffffffff00000 mfn=fbce0 nr=20 ret:-22
      (XEN) memory_map:remove: dom2 gfn=ffffffff00000 mfn=fbce0 nr=20
      (XEN) p2m.c:920:d0v0 gfn_to_mfn failed! gfn=ffffffff00000 type:4
      (XEN) p2m.c:920:d0v0 gfn_to_mfn failed! gfn=ffffffff00001 type:4
      ..
      (XEN) memory_map: error -22 removing dom2 access to [fbce0,fbcff]
      (DEBUG) 222 pci dev 04:0 BAR16 read upper 0x0ffffffff.
      (XEN) memory_map:remove: dom2 gfn=ffffffff00000 mfn=fbce0 nr=20
      (XEN) memory_map: error -22 removing dom2 access to [fbce0,fbcff]
      
      [The DEBUG is to illustate what the hvmloader was doing]
      
      Also we swap from xen_host_pci_long to using xen_host_pci_get_[byte,word,long].
      
      Otherwise we get:
      
      xen_pt_config_reg_init: Offset 0x0004 mismatch! Emulated=0x0000, host=0x2300017, syncing to 0x2300014.
      xen_pt_config_reg_init: Error: Offset 0x0004:0x2300014 expands past register size(2)!
      
      which is not surprising. We read the value as an 32-bit (from host),
      then operate it as a 16-bit - and the remainder is left unchanged.
      
      We end up writing the value as 16-bit (so 0014) to dev.config
      (as we use proper xen_set_host_[byte,word,long] so we don't spill
      to other registers) but in XenPTReg->data it is as 32-bit (0x2300014)!
      
      It is harmless as the read/write functions end up using an size mask
      and never modify the bits past 16-bit (reg->size is 2).
      
      This patch fixes the warnings by reading the value using the
      proper size.
      
      Note that the check for size is still left in-case the developer
      sets bits past the reg->size in the ->init routines. The author
      tried to fiddle with QEMU_BUILD_BUG to make this work but failed.
      Reviewed-by: NStefano Stabellini <stefano.stabellini@eu.citrix.com>
      Reported-by: NSander Eikelenboom <linux@eikelenboom.it>
      Signed-off-by: NKonrad Rzeszutek Wilk <konrad.wilk@oracle.com>
      Signed-off-by: NStefano Stabellini <stefano.stabellini@eu.citrix.com>
      2e87512e
    • K
      xen/pt: Use xen_host_pci_get_[byte|word] instead of dev.config · 6aa07b14
      Konrad Rzeszutek Wilk 提交于
      During init time we treat the dev.config area as a cache
      of the host view. However during execution time we treat it
      as guest view (by the generic PCI API). We need to sync Xen's
      code to the generic PCI API view. This is the first step
      by replacing all of the code that uses dev.config or
      pci_get_[byte|word] to get host value to actually use the
      xen_host_pci_get_[byte|word] functions.
      
      Interestingly in 'xen_pt_ptr_reg_init' we also needed to swap
      reg_field from uint32_t to uint8_t - since the access is only
      for one byte not four bytes. We can split this as a seperate
      patch however we would have to use a cast to thwart compiler
      warnings in the meantime.
      
      We also truncated 'flags' to 'flag' to make the code fit within
      the 80 characters.
      Reviewed-by: NStefano Stabellini <stefano.stabellini@eu.citrix.com>
      Signed-off-by: NKonrad Rzeszutek Wilk <konrad.wilk@oracle.com>
      Signed-off-by: NStefano Stabellini <stefano.stabellini@eu.citrix.com>
      6aa07b14
  2. 10 9月, 2015 16 次提交
  3. 08 9月, 2015 5 次提交
  4. 07 9月, 2015 16 次提交