Re: [PATCH v7 02/10] virtio-pci:decouple virtqueue from interrupt setting process

2021-06-02 Thread Jason Wang



在 2021/6/2 上午11:47, Cindy Lu 写道:

Decouple virtqueue from interrupt setting process to support config interrupt
Now the code for interrupt/vector are coupling
with the vq number, this patch will decouple the vritqueue
numbers from these functions.

Signed-off-by: Cindy Lu 
---
  hw/virtio/virtio-pci.c | 51 --
  1 file changed, 29 insertions(+), 22 deletions(-)

diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c
index b321604d9b..c5c080ec94 100644
--- a/hw/virtio/virtio-pci.c
+++ b/hw/virtio/virtio-pci.c
@@ -693,23 +693,17 @@ static void 
kvm_virtio_pci_vq_vector_release(VirtIOPCIProxy *proxy,
  }
  
  static int kvm_virtio_pci_irqfd_use(VirtIOPCIProxy *proxy,

- unsigned int queue_no,
+ EventNotifier *n,
   unsigned int vector)
  {
  VirtIOIRQFD *irqfd = >vector_irqfd[vector];
-VirtIODevice *vdev = virtio_bus_get_device(>bus);
-VirtQueue *vq = virtio_get_queue(vdev, queue_no);
-EventNotifier *n = virtio_queue_get_guest_notifier(vq);
  return kvm_irqchip_add_irqfd_notifier_gsi(kvm_state, n, NULL, 
irqfd->virq);
  }
  
  static void kvm_virtio_pci_irqfd_release(VirtIOPCIProxy *proxy,

-  unsigned int queue_no,
+  EventNotifier *n ,
unsigned int vector)
  {
-VirtIODevice *vdev = virtio_bus_get_device(>bus);
-VirtQueue *vq = virtio_get_queue(vdev, queue_no);
-EventNotifier *n = virtio_queue_get_guest_notifier(vq);
  VirtIOIRQFD *irqfd = >vector_irqfd[vector];
  int ret;
  
@@ -724,7 +718,8 @@ static int kvm_virtio_pci_vector_use(VirtIOPCIProxy *proxy, int nvqs)

  VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev);
  unsigned int vector;
  int ret, queue_no;
-
+VirtQueue *vq;
+EventNotifier *n;



Let's leave a newline here.



  for (queue_no = 0; queue_no < nvqs; queue_no++) {
  if (!virtio_queue_get_num(vdev, queue_no)) {
  break;
@@ -741,7 +736,9 @@ static int kvm_virtio_pci_vector_use(VirtIOPCIProxy *proxy, 
int nvqs)
   * Otherwise, delay until unmasked in the frontend.
   */
  if (vdev->use_guest_notifier_mask && k->guest_notifier_mask) {
-ret = kvm_virtio_pci_irqfd_use(proxy, queue_no, vector);
+vq = virtio_get_queue(vdev, queue_no);
+n = virtio_queue_get_guest_notifier(vq);
+ret = kvm_virtio_pci_irqfd_use(proxy, n, vector);
  if (ret < 0) {
  kvm_virtio_pci_vq_vector_release(proxy, vector);
  goto undo;
@@ -757,7 +754,9 @@ undo:
  continue;
  }
  if (vdev->use_guest_notifier_mask && k->guest_notifier_mask) {
-kvm_virtio_pci_irqfd_release(proxy, queue_no, vector);
+vq = virtio_get_queue(vdev, queue_no);
+n = virtio_queue_get_guest_notifier(vq);
+kvm_virtio_pci_irqfd_release(proxy, n, vector);
  }
  kvm_virtio_pci_vq_vector_release(proxy, vector);
  }
@@ -771,7 +770,8 @@ static void kvm_virtio_pci_vector_release(VirtIOPCIProxy 
*proxy, int nvqs)
  unsigned int vector;
  int queue_no;
  VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev);
-
+VirtQueue *vq;
+EventNotifier *n;



Similar here.



  for (queue_no = 0; queue_no < nvqs; queue_no++) {
  if (!virtio_queue_get_num(vdev, queue_no)) {
  break;
@@ -784,7 +784,9 @@ static void kvm_virtio_pci_vector_release(VirtIOPCIProxy 
*proxy, int nvqs)
   * Otherwise, it was cleaned when masked in the frontend.
   */
  if (vdev->use_guest_notifier_mask && k->guest_notifier_mask) {
-kvm_virtio_pci_irqfd_release(proxy, queue_no, vector);
+vq = virtio_get_queue(vdev, queue_no);
+n = virtio_queue_get_guest_notifier(vq);
+kvm_virtio_pci_irqfd_release(proxy, n, vector);
  }
  kvm_virtio_pci_vq_vector_release(proxy, vector);
  }
@@ -793,12 +795,11 @@ static void kvm_virtio_pci_vector_release(VirtIOPCIProxy 
*proxy, int nvqs)
  static int virtio_pci_vq_vector_unmask(VirtIOPCIProxy *proxy,
 unsigned int queue_no,
 unsigned int vector,
-   MSIMessage msg)
+   MSIMessage msg,
+   EventNotifier *n)
  {



A question: if this function needs to be used by configure interrupt, it 
needs rename. Otherwise we don't need to bother since it only deal with 
vq vector.




  VirtIODevice *vdev = virtio_bus_get_device(>bus);
  VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev);
-VirtQueue *vq = virtio_get_queue(vdev, queue_no);
-EventNotifier *n = virtio_queue_get_guest_notifier(vq);
  

Re: [PATCH v3 2/2] GitLab: Add "Feature Request" issue template.

2021-06-02 Thread Thomas Huth

On 03/06/2021 02.11, John Snow wrote:

Based on Peter Krempa's libvirt template, feature.md.

CC: Peter Krempa 
Signed-off-by: John Snow 
Reviewed-by: Stefan Hajnoczi 
---
  .gitlab/issue_templates/feature_request.md | 32 ++
  1 file changed, 32 insertions(+)
  create mode 100644 .gitlab/issue_templates/feature_request.md


Reviewed-by: Thomas Huth 




Re: [PATCH v3 1/2] GitLab: Add "Bug" issue reporting template

2021-06-02 Thread Thomas Huth

On 03/06/2021 02.11, John Snow wrote:

Based loosely on libvirt's template, written by Peter Krempa.

CC: Peter Krempa 
Signed-off-by: John Snow 
---
  .gitlab/issue_templates/bug.md | 63 ++
  1 file changed, 63 insertions(+)
  create mode 100644 .gitlab/issue_templates/bug.md


Reviewed-by: Thomas Huth 




[PATCH 5/8] Fix incorrect initialization of PCI BARs.

2021-06-02 Thread Jason Thorpe
Only program a BAR as a 64-bit MEM BAR if it really is a 64-bit MEM BAR.
Fixes an issue with the CMD646 IDE controller under NetBSD.

Improve some debug/info messages.

Signed-off-by: Jason Thorpe 
---
 pci.c | 7 ---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/pci.c b/pci.c
index ba05adb..5e9c906 100644
--- a/pci.c
+++ b/pci.c
@@ -84,7 +84,7 @@ pci_setup_device(int bdf, uint32_t *p_io_base, uint32_t 
*p_mem_base)
   device_id = pci_config_readw(bdf, PCI_DEVICE_ID);
   class_id = pci_config_readw(bdf, PCI_CLASS_DEVICE);
 
-  printf("PCI: %02x:%02x:%x class %04x id %04x:%04x\r\n",
+  printf("PCI: %d:%d:%d class %04x id %04x:%04x\r\n",
 PCI_BUS(bdf), PCI_SLOT(bdf), PCI_FUNC(bdf),
  class_id, vendor_id, device_id);
 
@@ -118,9 +118,10 @@ pci_setup_device(int bdf, uint32_t *p_io_base, uint32_t 
*p_mem_base)
  *p_base = addr + size;
  pci_config_writel(bdf, ofs, addr);
 
- printf("PCI:   region %d: %08x\r\n", region, addr);
+ printf("PCI:   region %d (BAR %02x): %08x\r\n", region, ofs, addr);
 
- if ((val & PCI_BASE_ADDRESS_MEM_TYPE_MASK)
+ if ((old & PCI_BASE_ADDRESS_SPACE_IO) == 0 &&
+ (old & PCI_BASE_ADDRESS_MEM_TYPE_MASK)
  == PCI_BASE_ADDRESS_MEM_TYPE_64)
{
  pci_config_writel(bdf, ofs + 4, 0);
-- 
2.30.2




[PATCH 4/8] Make some PCI macros available to other files. NFC.

2021-06-02 Thread Jason Thorpe
Move PCI_DEVFN(), PCI_BUS(), PCI_SLOT(), and PCI_FUNC() to pci.h.

Signed-off-by: Jason Thorpe 
---
 pci.c | 4 
 pci.h | 5 +
 2 files changed, 5 insertions(+), 4 deletions(-)

diff --git a/pci.c b/pci.c
index 87a101c..ba05adb 100644
--- a/pci.c
+++ b/pci.c
@@ -31,10 +31,6 @@
 #include "pci_regs.h"
 
 
-#define PCI_DEVFN(slot, func)  slot) & 0x1f) << 3) | ((func) & 0x07))
-#define PCI_BUS(devfn) ((devfn) >> 8)
-#define PCI_SLOT(devfn)(((devfn) >> 3) & 0x1f)
-#define PCI_FUNC(devfn)((devfn) & 0x07)
 #define PCI_SLOT_MAX   32
 #define PCI_FUNC_MAX   8
 #define PCI_REGION_ROM 6
diff --git a/pci.h b/pci.h
index b751c6f..b4a4f80 100644
--- a/pci.h
+++ b/pci.h
@@ -60,6 +60,11 @@ extern void pci_config_maskw(int bdf, int addr, uint16_t 
off, uint16_t on);
 
 extern int pci_next(int bdf, int *pmax);
 
+#define PCI_DEVFN(slot, func)  slot) & 0x1f) << 3) | ((func) & 0x07))
+#define PCI_BUS(devfn) ((devfn) >> 8)
+#define PCI_SLOT(devfn)(((devfn) >> 3) & 0x1f)
+#define PCI_FUNC(devfn)((devfn) & 0x07)
+
 #define foreachpci(BDF, MAX)   \
for (MAX = 0x0100, BDF = pci_next(0, ); \
 BDF >= 0;  \
-- 
2.30.2




[PATCH 3/8] Fix initialization of the hwrpb.hwrpb.cpuid field.

2021-06-02 Thread Jason Thorpe
Initialize the hwrpb.hwrpb.cpuid field with the primary CPU ID, not
the processor type, as per the architecture specification.  Some
operating systems check and assert this.

Improve a couple of comments.

Signed-off-by: Jason Thorpe 
---
 init.c | 29 ++---
 1 file changed, 22 insertions(+), 7 deletions(-)

diff --git a/init.c b/init.c
index 429a9ad..b3919b6 100644
--- a/init.c
+++ b/init.c
@@ -141,6 +141,7 @@ init_hwrpb (unsigned long memsize, unsigned long cpus)
   unsigned long pal_pages;
   unsigned long amask;
   unsigned long i;
+  unsigned long proc_type = EV4_CPU;
   
   hwrpb.hwrpb.phys_addr = PA();
 
@@ -162,12 +163,12 @@ init_hwrpb (unsigned long memsize, unsigned long cpus)
   switch (__builtin_alpha_implver())
 {
 case 0: /* EV4 */
-  hwrpb.hwrpb.cpuid = EV4_CPU;
+  proc_type = EV4_CPU;
   hwrpb.hwrpb.max_asn = 63;
   break;
 
 case 1: /* EV5 */
-  hwrpb.hwrpb.cpuid
+  proc_type
= ((amask & 0x101) == 0x101 ? PCA56_CPU /* MAX+BWX */
   : amask & 1 ? EV56_CPU   /* BWX */
   : EV5_CPU);
@@ -175,11 +176,16 @@ init_hwrpb (unsigned long memsize, unsigned long cpus)
   break;
 
 case 2: /* EV6 */
-  hwrpb.hwrpb.cpuid = (amask & 4 ? EV67_CPU : EV6_CPU);  /* CIX */
+  proc_type = (amask & 4 ? EV67_CPU : EV6_CPU); /* CIX */
   hwrpb.hwrpb.max_asn = 255;
   break;
 }
 
+  /* This field is the WHAMI of the primary CPU.  Just initialize
+ this to 0; CPU #0 is always the primary on real Alpha systems
+ (except for the TurboLaser).  */
+  hwrpb.hwrpb.cpuid = 0;
+
   hwrpb.hwrpb.pagesize = PAGE_SIZE;
   hwrpb.hwrpb.pa_bits = 40;
   hwrpb.hwrpb.sys_type = SYS_TYPE;
@@ -187,9 +193,18 @@ init_hwrpb (unsigned long memsize, unsigned long cpus)
   hwrpb.hwrpb.sys_revision = SYS_REVISION;
   for (i = 0; i < cpus; ++i)
 {
-  /* ??? Look up these bits.  Snagging the value examined by the kernel. */
+  /* Set the following PCS flags:
+(bit 2) Processor Available
+(bit 3) Processor Present
+(bit 6) PALcode Valid
+(bit 7) PALcode Memory Valid
+(bit 8) PALcode Loaded
+
+??? We really should be intializing the PALcode memory and
+scratch space fields if we're setting PMV, or not set PMV,
+but Linux checks for it, so...  */
   hwrpb.processor[i].flags = 0x1cc;
-  hwrpb.processor[i].type = hwrpb.hwrpb.cpuid;
+  hwrpb.processor[i].type = proc_type;
 }
 
   hwrpb.hwrpb.intr_freq = HZ * 4096;
@@ -257,8 +272,8 @@ init_i8259 (void)
   outb(0x04, PORT_PIC1_DATA);  /* ICW3: slave control INTC2 */
   outb(0x01, PORT_PIC1_DATA);  /* ICW4 */
 
-  /* Initialize level triggers.  The CY82C693UB that's on real alpha
- hardware doesn't have this; this is a PIIX extension.  However,
+  /* Initialize level triggers.  The CY82C693UB that's on some real alpha
+ systems controls these differently; we assume a PIIX here.  However,
  QEMU doesn't implement regular level triggers.  */
   outb(0xff, PORT_PIC2_ELCR);
   outb(0xff, PORT_PIC1_ELCR);
-- 
2.30.2




[PATCH 7/8] Provide a Console Terminal Block in the HWRPB.

2021-06-02 Thread Jason Thorpe
Provide a Console Terminal Block in the HWRPB so that operating systems
that depend on it can correctly initialize the console device.  In addition
to defining and filling out the structures, there are a couple of other
key changes:

- Redefine the a2 register passed by Qemu at start-up to also include
  some configuration flags, in addition to the CPU count, and define
  a flag to mirror the "-nographics" option.

- We need to initialize the HWRPB *after* initializing VGA, so that
  we'll know if a VGA device is present and in which slot for filling
  out the CTB.

Signed-off-by: Jason Thorpe 
---
 hwrpb.h  | 54 ++
 init.c   | 32 +---
 protos.h |  2 ++
 vgaio.c  |  2 ++
 4 files changed, 87 insertions(+), 3 deletions(-)

diff --git a/hwrpb.h b/hwrpb.h
index 2166bad..1531e68 100644
--- a/hwrpb.h
+++ b/hwrpb.h
@@ -146,6 +146,60 @@ struct crb_struct {
struct vf_map_struct map[1];
 };
 
+struct ctb_struct {
+   unsigned long type;
+   unsigned long unit;
+   unsigned long res0;
+   unsigned long len;
+   unsigned long ipl;
+   unsigned long tintr_vec;
+   unsigned long rintr_vec;
+   unsigned long term_type;
+   unsigned long keybd_type;
+   unsigned long keybd_trans;
+   unsigned long keybd_map;
+   unsigned long keybd_state;
+   unsigned long keybd_last;
+   unsigned long font_us;
+   unsigned long font_mcs;
+   unsigned long font_width;
+   unsigned long font_height;
+   unsigned long mon_width;
+   unsigned long mon_height;
+   unsigned long dpi;
+   unsigned long planes;
+   unsigned long cur_width;
+   unsigned long cur_height;
+   unsigned long head_cnt;
+   unsigned long opwindow;
+   unsigned long head_offset;
+   unsigned long putchar;
+   unsigned long io_state;
+   unsigned long listen_state;
+   unsigned long xaddr;
+   unsigned long turboslot;
+   unsigned long server_off;
+   unsigned long line_off;
+   unsigned char csd;
+};
+
+#define CTB_NONE   0x00
+#define CTB_PRINTERPORT0x02
+#define CTB_GRAPHICS   0x03
+#define CTB_TYPE4  0x04
+
+/*
+ * Format of the Console Terminal Block Type 4 `turboslot' field:
+ *
+ *  63   40 39   32 31 24 23  16 15   8 70
+ *  |  reserved|  channel  |  hose   | bus type |  bus | slot |
+ */
+
+#define CTB_TURBOSLOT_TYPE_TC   0   /* TURBOchannel */
+#define CTB_TURBOSLOT_TYPE_ISA  1   /* ISA */
+#define CTB_TURBOSLOT_TYPE_EISA 2   /* EISA */
+#define CTB_TURBOSLOT_TYPE_PCI  3   /* PCI */
+
 struct memclust_struct {
unsigned long start_pfn;
unsigned long numpages;
diff --git a/init.c b/init.c
index b3919b6..aee5cef 100644
--- a/init.c
+++ b/init.c
@@ -36,11 +36,20 @@
 
 #define HZ 1024
 
+/* Upon entry, register a2 contains configuration information from the VM:
+
+   bits 0-5 -- ncpus
+   bit  6   -- "nographics" option (used to initialize CTB)  */
+
+#define CONFIG_NCPUS(x)  ((x) & 63)
+#define CONFIG_NOGRAPHICS(x) ((x) & (1ull << 6))
+
 struct hwrpb_combine {
   struct hwrpb_struct hwrpb;
   struct percpu_struct processor[4];
   struct memdesc_struct md;
   struct memclust_struct mc[2];
+  struct ctb_struct ctb;
   struct crb_struct crb;
   struct procdesc_struct proc_dispatch;
   struct procdesc_struct proc_fixup;
@@ -59,6 +68,8 @@ struct hwrpb_combine hwrpb 
__attribute__((aligned(PAGE_SIZE)));
 
 void *last_alloc;
 bool have_vga;
+unsigned int pci_vga_bus;
+unsigned int pci_vga_dev;
 
 static void *
 alloc (unsigned long size, unsigned long align)
@@ -136,12 +147,13 @@ init_page_table(void)
 }
 
 static void
-init_hwrpb (unsigned long memsize, unsigned long cpus)
+init_hwrpb (unsigned long memsize, unsigned long config)
 {
   unsigned long pal_pages;
   unsigned long amask;
   unsigned long i;
   unsigned long proc_type = EV4_CPU;
+  unsigned long cpus = CONFIG_NCPUS(config);
   
   hwrpb.hwrpb.phys_addr = PA();
 
@@ -226,6 +238,19 @@ init_hwrpb (unsigned long memsize, unsigned long cpus)
   hwrpb.mc[1].start_pfn = pal_pages;
   hwrpb.mc[1].numpages = (memsize >> PAGE_SHIFT) - pal_pages;
 
+  hwrpb.hwrpb.ctbt_offset = offsetof(struct hwrpb_combine, ctb);
+  hwrpb.hwrpb.ctb_size = sizeof(hwrpb.ctb);
+  if (have_vga && !CONFIG_NOGRAPHICS(config))
+{
+  hwrpb.ctb.term_type = CTB_GRAPHICS;
+  hwrpb.ctb.turboslot = (CTB_TURBOSLOT_TYPE_PCI << 16) |
+   (pci_vga_bus << 8) | pci_vga_dev;
+}
+  else
+{
+  hwrpb.ctb.term_type = CTB_PRINTERPORT;
+}
+
   hwrpb.hwrpb.crb_offset = offsetof(struct hwrpb_combine, crb);
   hwrpb.crb.dispatch_va = _dispatch;
   hwrpb.crb.dispatch_pa = PA(_dispatch);
@@ -300,18 +325,19 @@ swppal(void *entry, void *pcb)
 }
 
 void
-do_start(unsigned long memsize, void (*kernel_entry)(void), unsigned long cpus)
+do_start(unsigned long memsize, 

[PATCH 6/8] Provide interrupt mapping information in PCI config registers.

2021-06-02 Thread Jason Thorpe
Use system-specific information to program the interrupt line register
with the interrupt mappings, which is what the SRM console does on real
hardware; some operating systems (e.g. NetBSD) use this information
rather than having interrupt mappings tables for every possible system
variation.

Signed-off-by: Jason Thorpe 
---
 pci.c | 20 +++-
 sys-clipper.h | 27 +++
 2 files changed, 46 insertions(+), 1 deletion(-)

diff --git a/pci.c b/pci.c
index 5e9c906..e3cab26 100644
--- a/pci.c
+++ b/pci.c
@@ -29,6 +29,7 @@
 #include "protos.h"
 #include "pci.h"
 #include "pci_regs.h"
+#include SYSTEM_H
 
 
 #define PCI_SLOT_MAX   32
@@ -132,7 +133,24 @@ pci_setup_device(int bdf, uint32_t *p_io_base, uint32_t 
*p_mem_base)
 
   pci_config_maskw(bdf, PCI_COMMAND, 0, PCI_COMMAND_IO | PCI_COMMAND_MEMORY);
 
-  /* Map the interrupt.  */
+  /* Map the interrupt and program the IRQ into the line register.
+ Some operating systems rely on the Console providing this information
+ in order to avoid having mapping tables for every possible system
+ variation.  */
+
+  const uint8_t pin = pci_config_readb(bdf, PCI_INTERRUPT_PIN);
+  const uint8_t slot = PCI_SLOT(bdf);
+  const int irq = MAP_PCI_INTERRUPT(slot, pin, class_id);
+
+  if (irq == -1)
+{
+  /* No interrupt mapping.  */
+  pci_config_writeb(bdf, PCI_INTERRUPT_LINE, 0xff);
+}
+  else
+{
+  pci_config_writeb(bdf, PCI_INTERRUPT_LINE, irq);
+}
 }
 
 void
diff --git a/sys-clipper.h b/sys-clipper.h
index 31094ff..4f563bf 100644
--- a/sys-clipper.h
+++ b/sys-clipper.h
@@ -27,4 +27,31 @@
 #define SYS_VARIATION  (5 << 10)
 #define SYS_REVISION   0
 
+#ifndef __ASSEMBLER__
+
+#define MAP_PCI_INTERRUPT(SLOT, PIN, CLASS_ID) \
+({ \
+  int IRQ; \
+   \
+  if (CLASS_ID == 0x0601)  \
+{  \
+  /* PCI-ISA bridge is hard-wired to IRQ 55 on real\
+ hardware, and comes in at a different SCB vector; \
+ force the line register to -1.  */\
+  IRQ = -1;\
+}  \
+  else if (PIN >= 1 && PIN <= 4)   \
+{  \
+  /* See hw/alpha/dp264.c:clipper_pci_map_irq()  */\
+  IRQ = (SLOT + 1) * 4 + (PIN - 1);\
+}  \
+  else \
+{  \
+  IRQ = -1;\
+}  \
+  IRQ; \
+})
+
+#endif /* ! __ASSEMBLER__ */
+
 #endif
-- 
2.30.2




[PATCH 0/8] PALcode fixes required to run NetBSD/alpha.

2021-06-02 Thread Jason Thorpe
Included here are a set of patches that fix issues in qemu-palcode needed
to run NetBSD/alpha under Qemu.  Some fix garden-variety bugs, some fix
deviations from the architecture specification or behavior of the SRM
console on real Alpha hardware.

Two of the changes (patch 6 and patch 7) also require other fixes in
Qemu itself, which will be submitted separately.  However, the changes
are fully compatible with existing Qemu alpha VMs because Linux does
not use the the SRM PCI interrupt mapping information (it has its own
tables for the system variations it supports) or the Console Terminal
Block in the HWRPB.

Jason Thorpe (8):
  Make qemu-palcode build environment standalone. NFC.
  Fix delivery of unaligned access exceptions.
  Fix initialization of the hwrpb.hwrpb.cpuid field.
  Make some PCI macros available to other files.  NFC.
  Fix incorrect initialization of PCI BARs.
  Provide interrupt mapping information in PCI config registers.
  Provide a Console Terminal Block in the HWRPB.
  Fixes for seconday CPU start-up.

 hwrpb.h   | 54 +++
 init.c| 88 +++
 memcpy.c  |  2 +-
 memset.c  |  2 +-
 pal.S | 15 ++---
 pci.c | 31 +-
 pci.h |  5 +++
 printf.c  |  4 +--
 protos.h  | 30 +++---
 sys-clipper.h | 27 
 vgaio.c   |  2 ++
 11 files changed, 218 insertions(+), 42 deletions(-)

-- 
2.30.2




[PATCH 8/8] Fixes for seconday CPU start-up.

2021-06-02 Thread Jason Thorpe
Changes to make secondary CPU start-up work on NetBSD, which depends
on some specific behavior in the architecture specification:

- Change the internal swppal() function to take the new VPTPTR and
  Procedure Value as explicit arguments.  Adapt do_start() to the
  new the new swppal() signature.

- In do_start_wait(), extract the new VPTPTR and PV from the relevant
  HWRPB fields, which will have been initialized by the OS, and pass
  them to swppal().

- In the SWPPAL PAL call, get the value to stuff into PV (r27) from
  a4 (r20), and add a comment describing why this implementation detail
  is allowed by the architecture specification.

Signed-off-by: Jason Thorpe 
---
 init.c | 25 -
 pal.S  | 13 ++---
 2 files changed, 26 insertions(+), 12 deletions(-)

diff --git a/init.c b/init.c
index aee5cef..bfe4d96 100644
--- a/init.c
+++ b/init.c
@@ -313,14 +313,16 @@ init_i8259 (void)
 }
 
 static void __attribute__((noreturn))
-swppal(void *entry, void *pcb)
+swppal(void *entry, void *pcb, unsigned long vptptr, unsigned long pv)
 {
   register int variant __asm__("$16") = 2; /* OSF/1 PALcode */
   register void *pc __asm__("$17") = entry;
   register unsigned long pa_pcb __asm__("$18") = PA(pcb);
-  register unsigned long vptptr __asm__("$19") = VPTPTR;
+  register unsigned long newvptptr __asm__("$19") = vptptr;
+  register unsigned long newpv __asm__("$20") = pv;
 
-  asm("call_pal 0x0a" : : "r"(variant), "r"(pc), "r"(pa_pcb), "r"(vptptr));
+  asm("call_pal 0x0a" : :
+  "r"(variant), "r"(pc), "r"(pa_pcb), "r"(newvptptr), "r"(newpv));
   __builtin_unreachable ();
 }
 
@@ -339,7 +341,9 @@ do_start(unsigned long memsize, void (*kernel_entry)(void),
   vgahw_init();
   init_hwrpb(memsize, config);
 
-  swppal(kernel_entry ? kernel_entry : do_console, );
+  void *new_pc = kernel_entry ? kernel_entry : do_console;
+
+  swppal(new_pc, , VPTPTR, (unsigned long)new_pc);
 }
 
 void
@@ -354,14 +358,16 @@ do_start_wait(unsigned long cpuid)
{
  /* ??? The only message I know of is "START\r\n".
 I can't be bothered to verify more than 4 characters.  */
- /* ??? The Linux kernel fills in, but does not require,
-CPU_restart_data.  It just sets that to the same address
-as CPU_restart itself.  Our swppal *does* put the PC into
-$26 and $27, the latter of which the kernel does rely upon.  */
+
+ /* Use use a private extension to SWPPAL to get the
+CPU_restart_data into $27.  Linux fills it in, but does
+not require it. Other operating systems, however, do use
+CPU_restart_data as part of secondary CPU start-up.  */
 
  unsigned int len = hwrpb.processor[cpuid].ipc_buffer[0];
  unsigned int msg = hwrpb.processor[cpuid].ipc_buffer[1];
  void *CPU_restart = hwrpb.hwrpb.CPU_restart;
+ unsigned long CPU_restart_data = hwrpb.hwrpb.CPU_restart_data;
  __sync_synchronize();
  hwrpb.hwrpb.rxrdy = 0;
 
@@ -369,7 +375,8 @@ do_start_wait(unsigned long cpuid)
{
  /* Set bootstrap in progress */
  hwrpb.processor[cpuid].flags |= 1;
- swppal(CPU_restart, hwrpb.processor[cpuid].hwpcb);
+ swppal(CPU_restart, hwrpb.processor[cpuid].hwpcb,
+hwrpb.hwrpb.vptb, CPU_restart_data);
}
}
 }
diff --git a/pal.S b/pal.S
index 015a829..7e3a62c 100644
--- a/pal.S
+++ b/pal.S
@@ -566,6 +566,8 @@ ENDFN   CallPal_Cserve_Cont
  * r17 (a1) = New PC
  * r18 (a2) = New PCB
  * r19 (a3) = New VptPtr
+ * r20 (a4) = New Procedure Value (to place into $27)
+ *(Non-standard; See note below.)
  * 
  * OUTPUT PARAMETERS:
  *
@@ -574,10 +576,15 @@ ENDFN CallPal_Cserve_Cont
  * 1 - Unknown PALcode variant
  * 2 - Known PALcode variant, but PALcode not loaded
  *
- * r26 (ra) = r27 (pv) = New PC
+ * r26 (ra) = New PC
+ * r27 (pv) = From r20
  * Note that this is non-architected, but is relied on by
  * the usage of SwpPal within our own console code in order
- * to simplify its use within C code.
+ * to simplify its use within C code.  We can get away with
+ * the extra non-standard argument (in $20) because as
+ * architected, all registers except SP and R0 are
+ * UNPREDICTABLE; therefore private internal usage is
+ * fine.
  *
  */
ORG_CALL_PAL_PRIV(0x0A)
@@ -624,7 +631,7 @@ CallPal_SwpPal_Cont:
mtpr$31, qemu_tbia  // Flush TLB for new PTBR
 
mov a1, $26
-   mov a1, $27
+   mov a4, $27
hw_ret  (a1)
 ENDFN  CallPal_SwpPal_Cont
.previous
-- 
2.30.2




[PATCH 2/8] Fix delivery of unaligned access exceptions.

2021-06-02 Thread Jason Thorpe
In the unaligned access exception vector, actually pass the return PC
in the exception frame.  This is required in order for unaligned access
fixup handlers in the operating system to work.

Signed-off-by: Jason Thorpe 
---
 pal.S | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/pal.S b/pal.S
index 64941a8..015a829 100644
--- a/pal.S
+++ b/pal.S
@@ -278,7 +278,7 @@ Pal_Unalign:
blbsp6, MchkBugCheck
addqp6, 4, p6   // increment past the faulting insn
 
-   STACK_FRAME p0, p1, p2, 1
+   STACK_FRAME p0, p6, p2, 1
 
mfprp0, ptEntUna
mfpr$gp, ptKgp
-- 
2.30.2




[PATCH 1/8] Make qemu-palcode build environment standalone. NFC.

2021-06-02 Thread Jason Thorpe
Don't include system headers.  Instead, provide standalone definitions
and declarations of types needed and functions used by the PALcode that
are compatible with the standard Alpha / GCC ABI.

Signed-off-by: Jason Thorpe 
---
 init.c   |  2 --
 memcpy.c |  2 +-
 memset.c |  2 +-
 printf.c |  4 +---
 protos.h | 30 +-
 5 files changed, 28 insertions(+), 12 deletions(-)

diff --git a/init.c b/init.c
index b53bab6..429a9ad 100644
--- a/init.c
+++ b/init.c
@@ -18,8 +18,6 @@
along with this program; see the file COPYING.  If not see
.  */
 
-#include 
-#include 
 #include "hwrpb.h"
 #include "osf.h"
 #include "ioport.h"
diff --git a/memcpy.c b/memcpy.c
index b6bbb74..9e1e913 100644
--- a/memcpy.c
+++ b/memcpy.c
@@ -8,7 +8,7 @@
  * This is a reasonably optimized memcpy() routine.
  */
 
-#include 
+#include "protos.h"
 
 /*
  * Note that the C code is written to be optimized into good assembly. However,
diff --git a/memset.c b/memset.c
index e8481dc..f9b0a6d 100644
--- a/memset.c
+++ b/memset.c
@@ -19,7 +19,7 @@
.  */
 
 
-#include 
+#include "protos.h"
 
 void *memset(void *optr, int ival, unsigned long size)
 {
diff --git a/printf.c b/printf.c
index 469b82c..0e1e128 100644
--- a/printf.c
+++ b/printf.c
@@ -18,10 +18,8 @@
along with this program; see the file COPYING.  If not see
.  */
 
-#include 
-#include 
-#include 
 #include "console.h"
+#include "protos.h"
 
 static int print_buf_pad(char *buf, int buflen, char *p, int width, int pad)
 {
diff --git a/protos.h b/protos.h
index 3ed1381..0d90be8 100644
--- a/protos.h
+++ b/protos.h
@@ -21,11 +21,31 @@
 #ifndef PROTOS_H
 #define PROTOS_H 1
 
-#include 
-#include 
-#include 
-#include 
-
+/* Stand-alone definitions for various types, compatible with
+   the Alpha Linux ABI and GCC.  This eliminates dependencies
+   on external headers.  */
+typedef unsigned char  uint8_t;
+typedef unsigned short uint16_t;
+typedef unsigned int   uint32_t;
+typedef unsigned long  uint64_t;
+typedef unsigned long  size_t;
+
+#define bool   _Bool
+#define true   1
+#define false  0
+
+#define offsetof(type, member) __builtin_offsetof(type, member)
+
+typedef __builtin_va_list va_list;
+#define va_start(ap, last) __builtin_va_start((ap), (last))
+#define va_arg __builtin_va_arg
+#define va_end(ap) __builtin_va_end(ap)
+
+#define NULL   ((void *)0)
+
+extern void *memset(void *, int, size_t);
+extern void *memcpy(void *, const void *, size_t);
+extern size_t strlen(const char *);
 
 /*
  * Call_Pal functions.
-- 
2.30.2




Re: [RFC v3 25/29] vhost: Add custom IOTLB translations to SVQ

2021-06-02 Thread Jason Wang



在 2021/6/3 上午1:51, Eugenio Perez Martin 写道:

On Wed, Jun 2, 2021 at 11:52 AM Jason Wang  wrote:


在 2021/5/20 上午12:28, Eugenio Pérez 写道:

Use translations added in IOVAReverseMaps in SVQ if the vhost device
does not support the mapping of the full qemu's virtual address space.
In other cases, Shadow Virtqueue still uses the qemu's virtual address
of the buffer pointed by the descriptor, which has been translated
already by qemu's VirtQueue machinery.


I'd say let stick to a single kind of translation (iova allocator) that
works for all the cases first and add optimizations on top.


Ok, I will start from here for the next revision.


Now every element needs to store the previous address also, so VirtQueue
can consume the elements properly. This adds a little overhead per VQ
element, having to allocate more memory to stash them. As a possible
optimization, this allocation could be avoided if the descriptor is not
a chain but a single one, but this is left undone.

Checking also for vhost_set_iotlb_callback to send used ring remapping.
This is only needed for kernel, and would print an error in case of
vhost devices with its own mapping (vdpa).

This could change for other callback, like checking for
vhost_force_iommu, enable_custom_iommu, or another. Another option could
be to, at least, extract the check of "is map(used, writable) needed?"
in another function. But at the moment just copy the check used in
vhost_dev_start here.

Signed-off-by: Eugenio Pérez 
---
   hw/virtio/vhost-shadow-virtqueue.c | 134 ++---
   hw/virtio/vhost.c  |  29 +--
   2 files changed, 145 insertions(+), 18 deletions(-)

diff --git a/hw/virtio/vhost-shadow-virtqueue.c 
b/hw/virtio/vhost-shadow-virtqueue.c
index 934d3bb27b..a92da979d1 100644
--- a/hw/virtio/vhost-shadow-virtqueue.c
+++ b/hw/virtio/vhost-shadow-virtqueue.c
@@ -10,12 +10,19 @@
   #include "hw/virtio/vhost-shadow-virtqueue.h"
   #include "hw/virtio/vhost.h"
   #include "hw/virtio/virtio-access.h"
+#include "hw/virtio/vhost-iova-tree.h"

   #include "standard-headers/linux/vhost_types.h"

   #include "qemu/error-report.h"
   #include "qemu/main-loop.h"

+typedef struct SVQElement {
+VirtQueueElement elem;
+void **in_sg_stash;
+void **out_sg_stash;


Any reason for the trick like this?

Can we simply use iovec and iov_copy() here?


At the moment the device writes the buffer directly to the guest's
memory, and SVQ only translates the descriptor. In this scenario,
there would be no need for iov_copy, isn't it?



It depends on which kinds of translation you used.

If I read the code correctly, stash is used for storing HVAs after the 
HVA->IOVA translation.


This looks exactly the work of iov (and do we guarantee the there will 
be a 1:1 translation?)


And if the mapping is 1:1 you can simply use iov_copy().

But this wont' be a option if we will always use iova allocator.




The reason for stash and unstash them was to allow the 1:1 mapping
with qemu memory and IOMMU and iova allocator to work with less
changes, In particular, the reason for unstash is that virtqueue_fill,
expects qemu pointers to set the guest memory page as dirty in
virtqueue_unmap_sg->dma_memory_unmap.

Now I think that just storing the iova address from the allocator in a
separated field and using a wrapper to get the IOVA addresses in SVQ
would be a better idea, so I would change to this if everyone agrees.



I agree.

Thanks




Thanks!


Thanks







Re: [RFC v3 17/29] vhost: Shadow virtqueue buffers forwarding

2021-06-02 Thread Jason Wang



在 2021/6/3 上午1:18, Eugenio Perez Martin 写道:

On Wed, Jun 2, 2021 at 11:51 AM Jason Wang  wrote:


在 2021/5/20 上午12:28, Eugenio Pérez 写道:

Initial version of shadow virtqueue that actually forward buffers. The
exposed addresses are the qemu's virtual address, so devices with IOMMU
that does not allow full mapping of qemu's address space does not work
at the moment.

Also for simplicity it only supports modern devices, that expects vring
in little endian, with split ring and no event idx or indirect
descriptors.

It reuses the VirtQueue code for the device part. The driver part is
based on Linux's virtio_ring driver, but with stripped functionality
and optimizations so it's easier to review.

Later commits will solve some of these concerns.


It would be more more easier to review if you squash those
"enhancements" into this patch.


Ok, they will be in the same commit for the next version.


Code also need to map used ring (device part) as RW in, and only in,
vhost-net. To map (or call vhost_device_iotlb_miss) inconditionally
would print an error in case of vhost devices with its own mapping
(vdpa).


I think we should not depend on the IOTLB miss. Instead, we should
program the device IOTLB before starting the svq. Or is there anything
that prevent you from doing this?


Sorry for being unclear, that is what I meant in the message: No other
device than kernel vhost needs the map (as "sent iotlb miss ahead"),
so we must make it conditional. Doing it unconditionally would make
nothing but an error appear on the screen, but it is incorrect anyway.

Is it clearer this way?



So what I'm worrying is the following code:

int vhost_device_iotlb_miss(struct vhost_dev *dev, uint64_t iova, int write)
{
...

    if (dev->shadow_vqs_enabled) {
    /* Shadow virtqueue translations in its Virtual Address Space */
    const VhostDMAMap *result;
    const VhostDMAMap needle = {
    .iova = iova,
    };

    result = vhost_iova_tree_find_taddr(>iova_map, );
        ...

}

I wonder the reason for doing that (sorry if I've asked this in the 
previous version).


I think the correct way is to use map those in the device IOTLB before, 
instead of using the miss.


Then we can have a unified code for vhost-vDPA and vhost-kernel.





To know if this call is needed, vhost_sw_live_migration_start_vq and
vhost_sw_live_migration_stop copy the test performed in
vhost_dev_start. Testing for the actual backend type could be cleaner,
or checking for non-NULL vhost_force_iommu, enable_custom_iommu, or
another vhostOp. We could extract this test in its own function too,
so its name could give a better hint. Just copy the vhost_dev_start
check at the moment.

Signed-off-by: Eugenio Pérez 
---
   hw/virtio/vhost-shadow-virtqueue.c | 205 +++--
   hw/virtio/vhost.c  | 134 ++-
   2 files changed, 325 insertions(+), 14 deletions(-)

diff --git a/hw/virtio/vhost-shadow-virtqueue.c 
b/hw/virtio/vhost-shadow-virtqueue.c
index ff50f12410..6d767fe248 100644
--- a/hw/virtio/vhost-shadow-virtqueue.c
+++ b/hw/virtio/vhost-shadow-virtqueue.c
@@ -9,6 +9,7 @@

   #include "hw/virtio/vhost-shadow-virtqueue.h"
   #include "hw/virtio/vhost.h"
+#include "hw/virtio/virtio-access.h"

   #include "standard-headers/linux/vhost_types.h"

@@ -48,9 +49,93 @@ typedef struct VhostShadowVirtqueue {

   /* Virtio device */
   VirtIODevice *vdev;
+
+/* Map for returning guest's descriptors */
+VirtQueueElement **ring_id_maps;
+
+/* Next head to expose to device */
+uint16_t avail_idx_shadow;
+
+/* Next free descriptor */
+uint16_t free_head;
+
+/* Last seen used idx */
+uint16_t shadow_used_idx;
+
+/* Next head to consume from device */
+uint16_t used_idx;
   } VhostShadowVirtqueue;

-/* Forward guest notifications */
+static void vhost_vring_write_descs(VhostShadowVirtqueue *svq,
+const struct iovec *iovec,
+size_t num, bool more_descs, bool write)
+{
+uint16_t i = svq->free_head, last = svq->free_head;
+unsigned n;
+uint16_t flags = write ? cpu_to_le16(VRING_DESC_F_WRITE) : 0;
+vring_desc_t *descs = svq->vring.desc;
+
+if (num == 0) {
+return;
+}
+
+for (n = 0; n < num; n++) {
+if (more_descs || (n + 1 < num)) {
+descs[i].flags = flags | cpu_to_le16(VRING_DESC_F_NEXT);
+} else {
+descs[i].flags = flags;
+}
+descs[i].addr = cpu_to_le64((hwaddr)iovec[n].iov_base);
+descs[i].len = cpu_to_le32(iovec[n].iov_len);
+
+last = i;
+i = cpu_to_le16(descs[i].next);
+}
+
+svq->free_head = le16_to_cpu(descs[last].next);
+}
+
+static unsigned vhost_shadow_vq_add_split(VhostShadowVirtqueue *svq,
+  VirtQueueElement *elem)
+{
+int head;
+unsigned avail_idx;
+vring_avail_t *avail = svq->vring.avail;
+
+

Re: [RFC v3 13/29] vhost: Add vhost_get_iova_range operation

2021-06-02 Thread Jason Wang



在 2021/6/1 下午3:17, Eugenio Perez Martin 写道:

On Thu, May 27, 2021 at 6:51 AM Jason Wang  wrote:


在 2021/5/27 上午1:49, Eugenio Perez Martin 写道:

On Wed, May 26, 2021 at 3:14 AM Jason Wang  wrote:

在 2021/5/20 上午12:28, Eugenio Pérez 写道:

For simplicity, If a device does not support this operation it means
that it can handle full (uint64_t)-1 iova address.

Note that, we probably need a separated patch for this.


Actually the comment is not in the right commit, the next one is the
one that uses it. Is that what you mean?


No, it's about the following suggestions.



And we need to this during vhost-vdpa initialization. If GPA is out of
the range, we need to fail the start of vhost-vdpa.


Note that this is for non-IOMMU case. For the case of vIOMMU we probably
need to validate it against address width or other similar attributes.


Right.

What should qemu do if the memory of the guest gets expanded outside
of the range? I think there is not a clear way to fail the memory
addition, isn't it?



I'm not sure, but I guess there should be a way to fail the memory hot-add.

(otherwise we can introduce the error reporting for them)

Thanks





Thanks



Right, that is still to-do.

Maybe a series with just these two commits and failing the start if
GPA is not in the range, as you say, would help to split the amount of
changes.

I will send it if no more comments arise about it.

Thanks!


THanks



Signed-off-by: Eugenio Pérez 
---
include/hw/virtio/vhost-backend.h |  5 +
hw/virtio/vhost-vdpa.c| 18 ++
hw/virtio/trace-events|  1 +
3 files changed, 24 insertions(+)

diff --git a/include/hw/virtio/vhost-backend.h 
b/include/hw/virtio/vhost-backend.h
index 94d3323905..bcb112c166 100644
--- a/include/hw/virtio/vhost-backend.h
+++ b/include/hw/virtio/vhost-backend.h
@@ -36,6 +36,7 @@ struct vhost_vring_addr;
struct vhost_scsi_target;
struct vhost_iotlb_msg;
struct vhost_virtqueue;
+struct vhost_vdpa_iova_range;

typedef int (*vhost_backend_init)(struct vhost_dev *dev, void *opaque);
typedef int (*vhost_backend_cleanup)(struct vhost_dev *dev);
@@ -127,6 +128,9 @@ typedef bool (*vhost_force_iommu_op)(struct vhost_dev *dev);

typedef int (*vhost_vring_pause_op)(struct vhost_dev *dev);

+typedef int (*vhost_get_iova_range)(struct vhost_dev *dev,
+hwaddr *first, hwaddr *last);
+
typedef struct VhostOps {
VhostBackendType backend_type;
vhost_backend_init vhost_backend_init;
@@ -173,6 +177,7 @@ typedef struct VhostOps {
vhost_get_device_id_op vhost_get_device_id;
vhost_vring_pause_op vhost_vring_pause;
vhost_force_iommu_op vhost_force_iommu;
+vhost_get_iova_range vhost_get_iova_range;
} VhostOps;

extern const VhostOps user_ops;
diff --git a/hw/virtio/vhost-vdpa.c b/hw/virtio/vhost-vdpa.c
index 01d2101d09..74fe92935e 100644
--- a/hw/virtio/vhost-vdpa.c
+++ b/hw/virtio/vhost-vdpa.c
@@ -579,6 +579,23 @@ static bool  vhost_vdpa_force_iommu(struct vhost_dev *dev)
return true;
}

+static int vhost_vdpa_get_iova_range(struct vhost_dev *dev,
+ hwaddr *first, hwaddr *last)
+{
+int ret;
+struct vhost_vdpa_iova_range range;
+
+ret = vhost_vdpa_call(dev, VHOST_VDPA_GET_IOVA_RANGE, );
+if (ret != 0) {
+return ret;
+}
+
+*first = range.first;
+*last = range.last;
+trace_vhost_vdpa_get_iova_range(dev, *first, *last);
+return ret;
+}
+
const VhostOps vdpa_ops = {
.backend_type = VHOST_BACKEND_TYPE_VDPA,
.vhost_backend_init = vhost_vdpa_init,
@@ -611,4 +628,5 @@ const VhostOps vdpa_ops = {
.vhost_get_device_id = vhost_vdpa_get_device_id,
.vhost_vq_get_addr = vhost_vdpa_vq_get_addr,
.vhost_force_iommu = vhost_vdpa_force_iommu,
+.vhost_get_iova_range = vhost_vdpa_get_iova_range,
};
diff --git a/hw/virtio/trace-events b/hw/virtio/trace-events
index c62727f879..5debe3a681 100644
--- a/hw/virtio/trace-events
+++ b/hw/virtio/trace-events
@@ -52,6 +52,7 @@ vhost_vdpa_set_vring_call(void *dev, unsigned int index, int fd) 
"dev: %p index:
vhost_vdpa_get_features(void *dev, uint64_t features) "dev: %p features: 
0x%"PRIx64
vhost_vdpa_set_owner(void *dev) "dev: %p"
vhost_vdpa_vq_get_addr(void *dev, void *vq, uint64_t desc_user_addr, uint64_t avail_user_addr, uint64_t 
used_user_addr) "dev: %p vq: %p desc_user_addr: 0x%"PRIx64" avail_user_addr: 
0x%"PRIx64" used_user_addr: 0x%"PRIx64
+vhost_vdpa_get_iova_range(void *dev, uint64_t first, uint64_t last) "dev: %p first: 
0x%"PRIx64" last: 0x%"PRIx64

# virtio.c
virtqueue_alloc_element(void *elem, size_t sz, unsigned in_num, unsigned out_num) 
"elem %p size %zd in_num %u out_num %u"





Re: [PATCH v2] target/ppc: fix single-step exception regression

2021-06-02 Thread David Gibson
On Wed, Jun 02, 2021 at 09:51:03AM -0300, Luis Pires wrote:
> Commit 6086c75 (target/ppc: Replace POWERPC_EXCP_BRANCH with
> DISAS_NORETURN) broke the generation of exceptions when
> CPU_SINGLE_STEP or CPU_BRANCH_STEP were set, due to nip always being
> reset to the address of the current instruction.
> This fix leaves nip untouched when generating the exception.
> 
> Signed-off-by: Luis Pires 
> Reported-by: Matheus Ferst 

Applied to ppc-for-6.1, thanks.

> ---
> v2:
>  - Removed incorrect nip update from ppc_tr_tb_stop()
> 
>  target/ppc/translate.c | 5 ++---
>  1 file changed, 2 insertions(+), 3 deletions(-)
> 
> diff --git a/target/ppc/translate.c b/target/ppc/translate.c
> index ea200f9637..14a0bb7168 100644
> --- a/target/ppc/translate.c
> +++ b/target/ppc/translate.c
> @@ -4646,8 +4646,7 @@ static void gen_lookup_and_goto_ptr(DisasContext *ctx)
>  if (sse & GDBSTUB_SINGLE_STEP) {
>  gen_debug_exception(ctx);
>  } else if (sse & (CPU_SINGLE_STEP | CPU_BRANCH_STEP)) {
> -uint32_t excp = gen_prep_dbgex(ctx);
> -gen_exception(ctx, excp);
> +gen_helper_raise_exception(cpu_env, 
> tcg_constant_i32(gen_prep_dbgex(ctx)));
>  } else {
>  tcg_gen_exit_tb(NULL, 0);
>  }
> @@ -9128,7 +9127,7 @@ static void ppc_tr_tb_stop(DisasContextBase *dcbase, 
> CPUState *cs)
>  }
>  /* else CPU_SINGLE_STEP... */
>  if (nip <= 0x100 || nip > 0xf00) {
> -gen_exception(ctx, gen_prep_dbgex(ctx));
> +gen_helper_raise_exception(cpu_env, 
> tcg_constant_i32(gen_prep_dbgex(ctx)));
>  return;
>  }
>  }

-- 
David Gibson| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au  | minimalist, thank you.  NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/~dgibson


signature.asc
Description: PGP signature


Re: [RFC v3 06/29] virtio-net: Honor VIRTIO_CONFIG_S_DEVICE_STOPPED

2021-06-02 Thread Jason Wang



在 2021/6/1 下午3:13, Eugenio Perez Martin 写道:

On Wed, May 26, 2021 at 3:10 AM Jason Wang  wrote:


在 2021/5/26 上午9:06, Jason Wang 写道:

在 2021/5/20 上午12:28, Eugenio Pérez 写道:

So the guest can stop and start net device. It implements the RFC
https://lists.oasis-open.org/archives/virtio-comment/202012/msg00027.html


To stop (as "pause") the device is required to migrate status and vring
addresses between device and SVQ.

This is a WIP commit: as with VIRTIO_F_QUEUE_STATE, is introduced in
virtio_config.h before of even proposing for the kernel, with no feature
flag, and, with no checking in the device. It also needs a modified
vp_vdpa driver that supports to set and retrieve status.

Signed-off-by: Eugenio Pérez 
---
   include/standard-headers/linux/virtio_config.h | 2 ++
   hw/net/virtio-net.c| 4 +++-
   2 files changed, 5 insertions(+), 1 deletion(-)

diff --git a/include/standard-headers/linux/virtio_config.h
b/include/standard-headers/linux/virtio_config.h
index 59fad3eb45..b3f6b1365d 100644
--- a/include/standard-headers/linux/virtio_config.h
+++ b/include/standard-headers/linux/virtio_config.h
@@ -40,6 +40,8 @@
   #define VIRTIO_CONFIG_S_DRIVER_OK4
   /* Driver has finished configuring features */
   #define VIRTIO_CONFIG_S_FEATURES_OK8
+/* Device is stopped */
+#define VIRTIO_CONFIG_S_DEVICE_STOPPED 32
   /* Device entered invalid state, driver must reset it */
   #define VIRTIO_CONFIG_S_NEEDS_RESET0x40
   /* We've given up on this device. */
diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
index 96a3cc8357..2d3caea289 100644
--- a/hw/net/virtio-net.c
+++ b/hw/net/virtio-net.c
@@ -198,7 +198,9 @@ static bool virtio_net_started(VirtIONet *n,
uint8_t status)
   {
   VirtIODevice *vdev = VIRTIO_DEVICE(n);
   return (status & VIRTIO_CONFIG_S_DRIVER_OK) &&
-(n->status & VIRTIO_NET_S_LINK_UP) && vdev->vm_running;
+(!(n->status & VIRTIO_CONFIG_S_DEVICE_STOPPED)) &&
+(n->status & VIRTIO_NET_S_LINK_UP) &&
+vdev->vm_running;
   }
 static void virtio_net_announce_notify(VirtIONet *net)


It looks to me this is only the part of pause.

For SVQ we need to switch vring addresses, and a full reset of the
device is required for that. Actually, the pause is just used to
recover

If you prefer this could be sent as a separate series where the full
pause/resume cycle is implemented, and then SVQ uses the pause part.
However there are no use for the resume part at the moment.



That would be fine if you can send it in another series.





And even for pause, I don't see anything that prevents rx/tx from being
executed? (E.g virtio_net_handle_tx_bh or virtio_net_handle_rx).


virtio_net_started is called from virtio_net_set_status. If
_S_DEVICE_STOPPED is true, the former return false, and variable
queue_started is false in the latter:
   queue_started =
 virtio_net_started(n, queue_status) && !n->vhost_started;

After that, it should work like a regular device reset or link down if
I'm not wrong, and the last part of virtio_net_set_status should
delete timer or cancel bh.



You are right.

Thanks





Thanks



We still need the resume?

Thanks







Re: [PATCH] hw/arm/boot: Use NUMA node ID in memory node name

2021-06-02 Thread Gavin Shan

Hi Drew,

On 6/2/21 9:36 PM, Andrew Jones wrote:

On Wed, Jun 02, 2021 at 11:09:32AM +1000, Gavin Shan wrote:

On 6/1/21 5:50 PM, Andrew Jones wrote:

On Tue, Jun 01, 2021 at 03:30:04PM +0800, Gavin Shan wrote:

We possibly populate empty nodes where memory isn't included and might
be hot added at late time. The FDT memory nodes can't be created due
to conflicts on their names if multiple empty nodes are specified.
For example, the VM fails to start with the following error messages.

/home/gavin/sandbox/qemu.main/build/qemu-system-aarch64  \
-accel kvm -machine virt,gic-version=host\
-cpu host -smp 4,sockets=2,cores=2,threads=1 -m 1024M,maxmem=64G \
-object memory-backend-ram,id=mem0,size=512M \
-object memory-backend-ram,id=mem1,size=512M \
-numa node,nodeid=0,cpus=0-1,memdev=mem0 \
-numa node,nodeid=1,cpus=2-3,memdev=mem1 \
-numa node,nodeid=2  \
-numa node,nodeid=3  \
  :
-device virtio-balloon-pci,id=balloon0,free-page-reporting=yes

qemu-system-aarch64: FDT: Failed to create subnode /memory@8000: \
 FDT_ERR_EXISTS

This fixes the issue by using NUMA node ID or zero in the memory node
name to avoid the conflicting memory node names. With this applied, the
VM can boot successfully with above command lines.

Signed-off-by: Gavin Shan 
---
   hw/arm/boot.c | 7 ++-
   1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/hw/arm/boot.c b/hw/arm/boot.c
index d7b059225e..3169bdf595 100644
--- a/hw/arm/boot.c
+++ b/hw/arm/boot.c
@@ -432,7 +432,12 @@ static int fdt_add_memory_node(void *fdt, uint32_t acells, 
hwaddr mem_base,
   char *nodename;
   int ret;
-nodename = g_strdup_printf("/memory@%" PRIx64, mem_base);
+if (numa_node_id >= 0) {
+nodename = g_strdup_printf("/memory@%d", numa_node_id);
+} else {
+nodename = g_strdup("/memory@0");
+}
+
   qemu_fdt_add_subnode(fdt, nodename);
   qemu_fdt_setprop_string(fdt, nodename, "device_type", "memory");
   ret = qemu_fdt_setprop_sized_cells(fdt, nodename, "reg", acells, 
mem_base,


[...]



Is it conventional to use the unit-address like this? If so, can you point
out where that's documented? If it's not conventional, then we shouldn't
do it. And then I'm not sure what we should do in this case. Here's a
couple links I found, but they don't really help...

https://devicetree-specification.readthedocs.io/en/latest/chapter2-devicetree-basics.html#sect-node-names
https://devicetree-specification.readthedocs.io/en/latest/chapter3-devicenodes.html#memory-node



As stated in the document (section 2.2.1.1). It's conventional to take the first
address of 'reg' property as unit-address, but it's not mandatory as I 
understand:

(1) In section 2.2.1.1, the bus can specify additional format to unit-address.


The bus type we're using is the physical memory map. Does it allow this
use of the unit-address? I still haven't seen that documented anywhere.


(2) The device node name isn't used to identify the device node in Linux kernel.
 They are actually identified by 'device_type' property.
 (drivers/of/fdt.c::early_init_dt_scan_memory())


This doesn't matter. We can't change DT node name formats just because
they may not impact Linux. We need to follow the DT standard and the Linux
convention.



I think it's still nice to include the unit-address in meory node's name. For 
the
conflicting nodes, we add more suffix like below. I can update the code in v2 if
it's preferred way to go.


I don't think we should change the semantics of the unit address at all,
not without either a) finding a document that says our use is OK or b)
getting it documented in the Linux kernel first.



[...]

I've sent one separate mail to check with Rob Herring. Hopefully he have
ideas as he is maintaining linux FDT subsystem. You have been included to
that thread. I didn't find something meaningful to this thread after doing
some google search either.

Yes, I agree with you we need to follow the specification strictly. It seems
it's uncertain about the 'physical memory map' bus binding requirements.

Thanks,
Gavin




Re: [RFC PATCH 2/2] migration/rdma: Enable use of g_autoptr with struct rdma_cm_event

2021-06-02 Thread lizhij...@fujitsu.com


On 03/06/2021 01.51, Philippe Mathieu-Daudé wrote:
> Since 00f2cfbbec6 ("glib: bump min required glib library version to
> 2.48") we can use g_auto/g_autoptr to have the compiler automatically
> free an allocated variable when it goes out of scope,
Glad to know this feature.

However per its code, a  'ack' does much more than just free the memory.
not sure g_autoptr have the ability to do the same.

2212 static void ucma_complete_event(struct cma_id_private *id_priv)
2213 {
2214 pthread_mutex_lock(_priv->mut);
2215 id_priv->events_completed++;
2216 pthread_cond_signal(_priv->cond);
2217 pthread_mutex_unlock(_priv->mut);
2218 }
2219
2220 static void ucma_complete_mc_event(struct cma_multicast *mc)
2221 {
 pthread_mutex_lock(>id_priv->mut);
2223 mc->events_completed++;
2224 pthread_cond_signal(>cond);
2225 mc->id_priv->events_completed++;
2226 pthread_cond_signal(>id_priv->cond);
2227 pthread_mutex_unlock(>id_priv->mut);
2228 }
2229
2230 int rdma_ack_cm_event(struct rdma_cm_event *event)
2231 {
2232 struct cma_event *evt;
2233
2234 if (!event)
2235 return ERR(EINVAL);
2236
2237 evt = container_of(event, struct cma_event, event);
2238
2239 if (evt->mc)
2240 ucma_complete_mc_event(evt->mc);
2241 else
2242 ucma_complete_event(evt->id_priv);
2243 free(evt);
2244 return 0;
2245 }

Thanks
Zhijian

> removing this
> burden on the developers.
>
> Per rdma_cm(7) and rdma_ack_cm_event(3) man pages:
>
>"rdma_ack_cm_event() - Free a communication event.
>
> All events which are allocated by rdma_get_cm_event() must be
> released, there should be a one-to-one correspondence between
> successful gets and acks. This call frees the event structure
> and any memory that it references."
>
> Since the 'ack' description doesn't explicit the event is also
> released (free'd), it is safer to use the GLib g_autoptr feature.
> The G_DEFINE_AUTOPTR_CLEANUP_FUNC() macro expects a single word
> for the type name, so add a type definition to achieve this.
> Convert to use g_autoptr and remove the rdma_ack_cm_event() calls.
>
> Inspired-by: Li Zhijian 
> Signed-off-by: Philippe Mathieu-Daudé 
> ---
> RFC: build-tested only
> ---
>   migration/rdma.c | 27 ++-
>   1 file changed, 10 insertions(+), 17 deletions(-)
>
> diff --git a/migration/rdma.c b/migration/rdma.c
> index b50ebb9183a..b703bf1b918 100644
> --- a/migration/rdma.c
> +++ b/migration/rdma.c
> @@ -38,6 +38,9 @@
>   #include "qom/object.h"
>   #include 
>   
> +typedef struct rdma_cm_event rdma_cm_event;
> +G_DEFINE_AUTOPTR_CLEANUP_FUNC(rdma_cm_event, rdma_ack_cm_event)
> +
>   /*
>* Print and error on both the Monitor and the Log file.
>*/
> @@ -939,7 +942,7 @@ static int qemu_rdma_resolve_host(RDMAContext *rdma, 
> Error **errp)
>   int ret;
>   struct rdma_addrinfo *res;
>   char port_str[16];
> -struct rdma_cm_event *cm_event;
> +g_autoptr(rdma_cm_event) cm_event = NULL;
>   char ip[40] = "unknown";
>   struct rdma_addrinfo *e;
>   
> @@ -1007,11 +1010,11 @@ route:
>   ERROR(errp, "result not equal to event_addr_resolved %s",
>   rdma_event_str(cm_event->event));
>   perror("rdma_resolve_addr");
> -rdma_ack_cm_event(cm_event);
>   ret = -EINVAL;
>   goto err_resolve_get_addr;
>   }
>   rdma_ack_cm_event(cm_event);
> +cm_event = NULL;
>   
>   /* resolve route */
>   ret = rdma_resolve_route(rdma->cm_id, RDMA_RESOLVE_TIMEOUT_MS);
> @@ -1028,11 +1031,9 @@ route:
>   if (cm_event->event != RDMA_CM_EVENT_ROUTE_RESOLVED) {
>   ERROR(errp, "result not equal to event_route_resolved: %s",
>   rdma_event_str(cm_event->event));
> -rdma_ack_cm_event(cm_event);
>   ret = -EINVAL;
>   goto err_resolve_get_addr;
>   }
> -rdma_ack_cm_event(cm_event);
>   rdma->verbs = rdma->cm_id->verbs;
>   qemu_rdma_dump_id("source_resolve_host", rdma->cm_id->verbs);
>   qemu_rdma_dump_gid("source_resolve_host", rdma->cm_id);
> @@ -1501,7 +1502,7 @@ static uint64_t qemu_rdma_poll(RDMAContext *rdma, 
> uint64_t *wr_id_out,
>*/
>   static int qemu_rdma_wait_comp_channel(RDMAContext *rdma)
>   {
> -struct rdma_cm_event *cm_event;
> +g_autoptr(rdma_cm_event) cm_event = NULL;
>   int ret = -1;
>   
>   /*
> @@ -2503,7 +2504,7 @@ static int qemu_rdma_connect(RDMAContext *rdma, Error 
> **errp, bool return_path)
> .private_data = ,
> .private_data_len = sizeof(cap),
>   };
> -struct rdma_cm_event *cm_event;
> +g_autoptr(rdma_cm_event) cm_event = NULL;
>   int ret;
>   
>   /*
> @@ -2544,7 +2545,6 @@ static int qemu_rdma_connect(RDMAContext *rdma, Error 
> **errp, bool return_path)
>   if (cm_event->event != RDMA_CM_EVENT_ESTABLISHED) {
>   perror("rdma_get_cm_event != 

[PATCH v3 18/19] scripts/qom-fuse: add redirection shim to python/qemu/qmp/qom-fuse.py

2021-06-02 Thread John Snow
By leaving the script absent for a commit, git-blame travels to the new
file instead of staying on the shim.

Signed-off-by: John Snow 
Reviewed-by: Philippe Mathieu-Daudé 
---
 scripts/qmp/qom-fuse | 11 +++
 1 file changed, 11 insertions(+)
 create mode 100755 scripts/qmp/qom-fuse

diff --git a/scripts/qmp/qom-fuse b/scripts/qmp/qom-fuse
new file mode 100755
index 000..a58c8ef9793
--- /dev/null
+++ b/scripts/qmp/qom-fuse
@@ -0,0 +1,11 @@
+#!/usr/bin/env python3
+
+import os
+import sys
+
+sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..', 'python'))
+from qemu.qmp.qom_fuse import QOMFuse
+
+
+if __name__ == '__main__':
+sys.exit(QOMFuse.entry_point())
-- 
2.31.1




[PATCH v3 14/19] scripts/qom-fuse: ensure QOMFuse.read always returns bytes

2021-06-02 Thread John Snow
- Use FuseOSError to signal ENOENT instead of returning it
- Wrap qom-get in str(), as we don't always know its type
- The empty return should be b'', not ''.

Signed-off-by: John Snow 
Reviewed-by: Philippe Mathieu-Daudé 
---
 scripts/qmp/qom-fuse | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/scripts/qmp/qom-fuse b/scripts/qmp/qom-fuse
index 703a97e75ff..0d11f731526 100755
--- a/scripts/qmp/qom-fuse
+++ b/scripts/qmp/qom-fuse
@@ -127,19 +127,19 @@ class QOMFuse(QOMCommand, Operations):
 
 def read(self, path, size, offset, fh):
 if not self.is_property(path):
-return -ENOENT
+raise FuseOSError(ENOENT)
 
 path, prop = path.rsplit('/', 1)
 if path == '':
 path = '/'
 try:
-data = self.qmp.command('qom-get', path=path, property=prop)
+data = str(self.qmp.command('qom-get', path=path, property=prop))
 data += '\n'  # make values shell friendly
 except QMPResponseError as err:
 raise FuseOSError(EPERM) from err
 
 if offset > len(data):
-return ''
+return b''
 
 return bytes(data[offset:][:size], encoding='utf-8')
 
-- 
2.31.1




[PATCH v3 19/19] python/qmp: add fuse command to 'qom' tools

2021-06-02 Thread John Snow
The 'fuse' command will be unavailable if 'fusepy' is not installed. It
will simply not load and subsequently be unavailable as a subcommand.

Signed-off-by: John Snow 
---
 python/qemu/qmp/qom.py | 14 --
 python/setup.cfg   |  1 +
 2 files changed, 13 insertions(+), 2 deletions(-)

diff --git a/python/qemu/qmp/qom.py b/python/qemu/qmp/qom.py
index 7fe1448b5d9..7ec7843d57a 100644
--- a/python/qemu/qmp/qom.py
+++ b/python/qemu/qmp/qom.py
@@ -1,7 +1,7 @@
 """
 QEMU Object Model testing tools.
 
-usage: qom [-h] {set,get,list,tree} ...
+usage: qom [-h] {set,get,list,tree,fuse} ...
 
 Query and manipulate QOM data
 
@@ -9,11 +9,12 @@
   -h, --help   show this help message and exit
 
 QOM commands:
-  {set,get,list,tree}
+  {set,get,list,tree,fuse}
 setSet a QOM property value
 getGet a QOM property value
 list   List QOM properties at a given path
 tree   Show QOM tree from a given path
+fuse   Mount a QOM tree as a FUSE filesystem
 """
 ##
 # Copyright John Snow 2020, for Red Hat, Inc.
@@ -35,6 +36,15 @@
 from .qom_common import QOMCommand
 
 
+try:
+from .qom_fuse import QOMFuse
+except ModuleNotFoundError as err:
+if err.name != 'fuse':
+raise
+else:
+assert issubclass(QOMFuse, QOMCommand)
+
+
 class QOMSet(QOMCommand):
 """
 QOM Command - Set a property to a given value.
diff --git a/python/setup.cfg b/python/setup.cfg
index aca6f311853..6b6be8b03c6 100644
--- a/python/setup.cfg
+++ b/python/setup.cfg
@@ -49,6 +49,7 @@ console_scripts =
 qom-get = qemu.qmp.qom:QOMGet.entry_point
 qom-list = qemu.qmp.qom:QOMList.entry_point
 qom-tree = qemu.qmp.qom:QOMTree.entry_point
+qom-fuse = qemu.qmp.qom_fuse:QOMFuse.entry_point [fuse]
 
 [flake8]
 extend-ignore = E722  # Prefer pylint's bare-except checks to flake8's
-- 
2.31.1




[PATCH v3 13/19] scripts/qom-fuse: use QOMCommand.qom_list()

2021-06-02 Thread John Snow
the qom_list method provides a type-safe object that's easier to type
check, so switch to using it.

Signed-off-by: John Snow 
---
 scripts/qmp/qom-fuse | 18 --
 1 file changed, 8 insertions(+), 10 deletions(-)

diff --git a/scripts/qmp/qom-fuse b/scripts/qmp/qom-fuse
index 1676fb78d99..703a97e75ff 100755
--- a/scripts/qmp/qom-fuse
+++ b/scripts/qmp/qom-fuse
@@ -94,7 +94,7 @@ class QOMFuse(QOMCommand, Operations):
 def is_object(self, path):
 """Is the given QOM path an object?"""
 try:
-self.qmp.command('qom-list', path=path)
+self.qom_list(path)
 return True
 except QMPResponseError:
 return False
@@ -105,8 +105,8 @@ class QOMFuse(QOMCommand, Operations):
 if path == '':
 path = '/'
 try:
-for item in self.qmp.command('qom-list', path=path):
-if item['name'] == prop:
+for item in self.qom_list(path):
+if item.name == prop:
 return True
 return False
 except QMPResponseError:
@@ -118,11 +118,9 @@ class QOMFuse(QOMCommand, Operations):
 if path == '':
 path = '/'
 try:
-for item in self.qmp.command('qom-list', path=path):
-if item['name'] == prop:
-if item['type'].startswith('link<'):
-return True
-return False
+for item in self.qom_list(path):
+if item.name == prop and item.link:
+return True
 return False
 except QMPResponseError:
 return False
@@ -200,8 +198,8 @@ class QOMFuse(QOMCommand, Operations):
 def readdir(self, path, fh):
 yield '.'
 yield '..'
-for item in self.qmp.command('qom-list', path=path):
-yield str(item['name'])
+for item in self.qom_list(path):
+yield item.name
 
 
 if __name__ == '__main__':
-- 
2.31.1




[PATCH v3 17/19] scripts/qom-fuse: move to python/qemu/qmp/qom_fuse.py

2021-06-02 Thread John Snow
Move qom-fuse over to the python package now that it passes the
linter. Update the import paradigms so that it continues to pass in the
context of the Python package.

Signed-off-by: John Snow 
---
 scripts/qmp/qom-fuse => python/qemu/qmp/qom_fuse.py | 12 ++--
 1 file changed, 2 insertions(+), 10 deletions(-)
 rename scripts/qmp/qom-fuse => python/qemu/qmp/qom_fuse.py (95%)
 mode change 100755 => 100644

diff --git a/scripts/qmp/qom-fuse b/python/qemu/qmp/qom_fuse.py
old mode 100755
new mode 100644
similarity index 95%
rename from scripts/qmp/qom-fuse
rename to python/qemu/qmp/qom_fuse.py
index a5a7a304a3e..43f4671fdb1
--- a/scripts/qmp/qom-fuse
+++ b/python/qemu/qmp/qom_fuse.py
@@ -1,4 +1,3 @@
-#!/usr/bin/env python3
 """
 QEMU Object Model FUSE filesystem tool
 
@@ -35,7 +34,6 @@
 
 import argparse
 from errno import ENOENT, EPERM
-import os
 import stat
 import sys
 from typing import (
@@ -50,10 +48,8 @@
 import fuse
 from fuse import FUSE, FuseOSError, Operations
 
-
-sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..', 'python'))
-from qemu.qmp import QMPResponseError
-from qemu.qmp.qom_common import QOMCommand
+from . import QMPResponseError
+from .qom_common import QOMCommand
 
 
 fuse.fuse_python_api = (0, 2)
@@ -208,7 +204,3 @@ def readdir(self, path: str, fh: IO[bytes]) -> 
Iterator[str]:
 yield '..'
 for item in self.qom_list(path):
 yield item.name
-
-
-if __name__ == '__main__':
-sys.exit(QOMFuse.entry_point())
-- 
2.31.1




[PATCH v3 11/19] scripts/qom-fuse: Add docstrings

2021-06-02 Thread John Snow
The methods inherited from fuse don't need docstrings; that's up to
fusepy to handle.

Signed-off-by: John Snow 
---
 scripts/qmp/qom-fuse | 21 +++--
 1 file changed, 19 insertions(+), 2 deletions(-)

diff --git a/scripts/qmp/qom-fuse b/scripts/qmp/qom-fuse
index 805e99c8ecd..1fb3008a167 100755
--- a/scripts/qmp/qom-fuse
+++ b/scripts/qmp/qom-fuse
@@ -1,7 +1,19 @@
 #!/usr/bin/env python3
+"""
+QEMU Object Model FUSE filesystem tool
+
+This script offers a simple FUSE filesystem within which the QOM tree
+may be browsed, queried and edited using traditional shell tooling.
+
+This script requires the 'fusepy' python package.
+
+ENV:
+QMP_SOCKET: Path to the QMP server socket
+
+Usage:
+qom-fuse /mount/to/here
+"""
 ##
-# QEMU Object Model test tools
-#
 # Copyright IBM, Corp. 2012
 # Copyright (C) 2020 Red Hat, Inc.
 #
@@ -30,6 +42,7 @@ fuse.fuse_python_api = (0, 2)
 
 
 class QOMFS(Operations):
+"""QOMFS implements fuse.Operations to provide a QOM filesystem."""
 def __init__(self, qmp):
 self.qmp = qmp
 self.qmp.connect()
@@ -37,6 +50,7 @@ class QOMFS(Operations):
 self.ino_count = 1
 
 def get_ino(self, path):
+"""Get an inode number for a given QOM path."""
 if path in self.ino_map:
 return self.ino_map[path]
 self.ino_map[path] = self.ino_count
@@ -44,6 +58,7 @@ class QOMFS(Operations):
 return self.ino_map[path]
 
 def is_object(self, path):
+"""Is the given QOM path an object?"""
 try:
 self.qmp.command('qom-list', path=path)
 return True
@@ -51,6 +66,7 @@ class QOMFS(Operations):
 return False
 
 def is_property(self, path):
+"""Is the given QOM path a property?"""
 path, prop = path.rsplit('/', 1)
 if path == '':
 path = '/'
@@ -63,6 +79,7 @@ class QOMFS(Operations):
 return False
 
 def is_link(self, path):
+"""Is the given QOM path a link?"""
 path, prop = path.rsplit('/', 1)
 if path == '':
 path = '/'
-- 
2.31.1




[PATCH v3 08/19] scripts/qom-fuse: apply flake8 rules

2021-06-02 Thread John Snow
flake8 still has one warning because of the sys.path hack, but that will
be going away by the end of this patch series.

Signed-off-by: John Snow 
---
 scripts/qmp/qom-fuse | 81 +++-
 1 file changed, 43 insertions(+), 38 deletions(-)

diff --git a/scripts/qmp/qom-fuse b/scripts/qmp/qom-fuse
index 62deb9adb12..ca30e928679 100755
--- a/scripts/qmp/qom-fuse
+++ b/scripts/qmp/qom-fuse
@@ -9,13 +9,12 @@
 #  Anthony Liguori   
 #  Markus Armbruster 
 #
-# This work is licensed under the terms of the GNU GPL, version 2 or later.  
See
-# the COPYING file in the top-level directory.
+# This work is licensed under the terms of the GNU GPL, version 2 or later.
+# See the COPYING file in the top-level directory.
 ##
 
-from errno import *
+from errno import ENOENT, EPERM
 import os
-import posix
 import stat
 import sys
 
@@ -29,6 +28,7 @@ from qemu.qmp import QEMUMonitorProtocol
 
 fuse.fuse_python_api = (0, 2)
 
+
 class QOMFS(Operations):
 def __init__(self, qmp):
 self.qmp = qmp
@@ -45,7 +45,7 @@ class QOMFS(Operations):
 
 def is_object(self, path):
 try:
-items = self.qmp.command('qom-list', path=path)
+self.qmp.command('qom-list', path=path)
 return True
 except:
 return False
@@ -85,7 +85,7 @@ class QOMFS(Operations):
 path = '/'
 try:
 data = self.qmp.command('qom-get', path=path, property=prop)
-data += '\n' # make values shell friendly
+data += '\n'  # make values shell friendly
 except:
 raise FuseOSError(EPERM)
 
@@ -104,38 +104,44 @@ class QOMFS(Operations):
 
 def getattr(self, path, fh=None):
 if self.is_link(path):
-value = { 'st_mode': 0o755 | stat.S_IFLNK,
-  'st_ino': self.get_ino(path),
-  'st_dev': 0,
-  'st_nlink': 2,
-  'st_uid': 1000,
-  'st_gid': 1000,
-  'st_size': 4096,
-  'st_atime': 0,
-  'st_mtime': 0,
-  'st_ctime': 0 }
+value = {
+'st_mode': 0o755 | stat.S_IFLNK,
+'st_ino': self.get_ino(path),
+'st_dev': 0,
+'st_nlink': 2,
+'st_uid': 1000,
+'st_gid': 1000,
+'st_size': 4096,
+'st_atime': 0,
+'st_mtime': 0,
+'st_ctime': 0
+}
 elif self.is_object(path):
-value = { 'st_mode': 0o755 | stat.S_IFDIR,
-  'st_ino': self.get_ino(path),
-  'st_dev': 0,
-  'st_nlink': 2,
-  'st_uid': 1000,
-  'st_gid': 1000,
-  'st_size': 4096,
-  'st_atime': 0,
-  'st_mtime': 0,
-  'st_ctime': 0 }
+value = {
+'st_mode': 0o755 | stat.S_IFDIR,
+'st_ino': self.get_ino(path),
+'st_dev': 0,
+'st_nlink': 2,
+'st_uid': 1000,
+'st_gid': 1000,
+'st_size': 4096,
+'st_atime': 0,
+'st_mtime': 0,
+'st_ctime': 0
+}
 elif self.is_property(path):
-value = { 'st_mode': 0o644 | stat.S_IFREG,
-  'st_ino': self.get_ino(path),
-  'st_dev': 0,
-  'st_nlink': 1,
-  'st_uid': 1000,
-  'st_gid': 1000,
-  'st_size': 4096,
-  'st_atime': 0,
-  'st_mtime': 0,
-  'st_ctime': 0 }
+value = {
+'st_mode': 0o644 | stat.S_IFREG,
+'st_ino': self.get_ino(path),
+'st_dev': 0,
+'st_nlink': 1,
+'st_uid': 1000,
+'st_gid': 1000,
+'st_size': 4096,
+'st_atime': 0,
+'st_mtime': 0,
+'st_ctime': 0
+}
 else:
 raise FuseOSError(ENOENT)
 return value
@@ -146,8 +152,7 @@ class QOMFS(Operations):
 for item in self.qmp.command('qom-list', path=path):
 yield str(item['name'])
 
+
 if __name__ == '__main__':
-import os
-
 fuse = FUSE(QOMFS(QEMUMonitorProtocol(os.environ['QMP_SOCKET'])),
 sys.argv[1], foreground=True)
-- 
2.31.1




[PATCH v3 16/19] python: add optional FUSE dependencies

2021-06-02 Thread John Snow
In preparation for moving qom-fuse over to the python package, we need
some new dependencies to support it.

Add an optional 'fusepy' dependency that users of the package can opt
into with e.g. "pip install qemu[fuse]" which installs the requirements
necessary to obtain the additional functionality.

Add the same fusepy dependency to the 'devel' extras group --
unfortunately I do not see a way for optional groups to imply other
optional groups at present, so the dependency is repeated. The
development group needs to include the full set of dependencies for the
purpose of static analysis of all features offered by this library.

Lastly, add the [fuse] extras group to tox's configuration as a
workaround so that if a stale tox environment is found when running
`make check-tox`, tox will know to rebuild its environments.

Signed-off-by: John Snow 
---
 python/Pipfile.lock | 6 ++
 python/setup.cfg| 9 -
 2 files changed, 14 insertions(+), 1 deletion(-)

diff --git a/python/Pipfile.lock b/python/Pipfile.lock
index f2a3f91d0fa..5bb3f1b6351 100644
--- a/python/Pipfile.lock
+++ b/python/Pipfile.lock
@@ -67,6 +67,12 @@
 "markers": "python_version >= '2.7' and python_version not in 
'3.0, 3.1, 3.2, 3.3, 3.4'",
 "version": "==3.9.2"
 },
+"fusepy": {
+"hashes": [
+
"sha256:72ff783ec2f43de3ab394e3f7457605bf04c8cf288a2f4068b4cde141d4ee6bd"
+],
+"version": "==3.0.1"
+},
 "importlib-metadata": {
 "hashes": [
 
"sha256:8c501196e49fb9df5df43833bdb1e4328f64847763ec8a50703148b73784d581",
diff --git a/python/setup.cfg b/python/setup.cfg
index ba8d29fd62d..aca6f311853 100644
--- a/python/setup.cfg
+++ b/python/setup.cfg
@@ -32,11 +32,16 @@ packages =
 devel =
 avocado-framework >= 87.0
 flake8 >= 3.6.0
+fusepy >= 2.0.4
 isort >= 5.1.2
 mypy >= 0.770
 pylint >= 2.8.0
 tox >= 3.18.0
 
+# Provides qom-fuse functionality
+fuse =
+fusepy >= 2.0.4
+
 [options.entry_points]
 console_scripts =
 qom = qemu.qmp.qom:main
@@ -114,6 +119,8 @@ envlist = py36, py37, py38, py39, py310
 
 [testenv]
 allowlist_externals = make
-deps = .[devel]
+deps =
+.[devel]
+.[fuse]  # Workaround to trigger tox venv rebuild
 commands =
 make check
-- 
2.31.1




[PATCH v3 09/19] python: Add 'fh' to known-good variable names

2021-06-02 Thread John Snow
fd and fh are fine: we often use these for "file descriptor" or "file
handle" accordingly. It is rarely the case that you need to enforce a
more semantically meaningful name beyond "This is the file we are using
right now."

While we're here: add comments for all of the non-standard pylint
names. (And the underscore.)

Signed-off-by: John Snow 
---
 python/setup.cfg | 7 ---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/python/setup.cfg b/python/setup.cfg
index a19029d5388..c9b9445af98 100644
--- a/python/setup.cfg
+++ b/python/setup.cfg
@@ -78,9 +78,10 @@ good-names=i,
k,
ex,
Run,
-   _,
-   fd,
-   c,
+   _,   # By convention: Unused variable
+   fh,  # fh = open(...)
+   fd,  # fd = os.open(...)
+   c,   # for c in string: ...
 
 [pylint.similarities]
 # Ignore imports when computing similarities.
-- 
2.31.1




[PATCH v3 07/19] scripts/qom-fuse: apply isort rules

2021-06-02 Thread John Snow
Hint: you can use symlinks to create qom_fuse.py in python/qemu/qmp/ and
point to scripts/qom-fuse to apply the standard linting rules to this
script.

Signed-off-by: John Snow 
Reviewed-by: Philippe Mathieu-Daudé 
---
 scripts/qmp/qom-fuse | 12 +---
 1 file changed, 9 insertions(+), 3 deletions(-)

diff --git a/scripts/qmp/qom-fuse b/scripts/qmp/qom-fuse
index 7c7cff8edfb..62deb9adb12 100755
--- a/scripts/qmp/qom-fuse
+++ b/scripts/qmp/qom-fuse
@@ -13,14 +13,20 @@
 # the COPYING file in the top-level directory.
 ##
 
-import fuse, stat
-from fuse import FUSE, FuseOSError, Operations
-import os, posix, sys
 from errno import *
+import os
+import posix
+import stat
+import sys
+
+import fuse
+from fuse import FUSE, FuseOSError, Operations
+
 
 sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..', 'python'))
 from qemu.qmp import QEMUMonitorProtocol
 
+
 fuse.fuse_python_api = (0, 2)
 
 class QOMFS(Operations):
-- 
2.31.1




[PATCH v3 15/19] scripts/qom-fuse: add static type hints

2021-06-02 Thread John Snow
Because fusepy does not have type hints, add some targeted warning
suppressions.

Namely, we need to allow subclassing something of an unknown type (in
qom_fuse.py), and we need to allow missing imports (recorded against
fuse itself) because mypy will be unable to import fusepy (even when
installed) as it has no types nor type stubs available.

Note: Until now, it was possible to run invocations like 'mypy qemu/'
from ./python and have that work. However, these targeted suppressions
require that you run 'mypy -p qemu/' instead. The correct, canonical
invocation is recorded in ./python/tests/mypy.sh and all of the various
CI invocations always use this correct form.

Signed-off-by: John Snow 
---
 python/setup.cfg |  8 
 scripts/qmp/qom-fuse | 26 +-
 2 files changed, 25 insertions(+), 9 deletions(-)

diff --git a/python/setup.cfg b/python/setup.cfg
index c9b9445af98..ba8d29fd62d 100644
--- a/python/setup.cfg
+++ b/python/setup.cfg
@@ -57,6 +57,14 @@ python_version = 3.6
 warn_unused_configs = True
 namespace_packages = True
 
+[mypy-qemu.qmp.qom_fuse]
+# fusepy has no type stubs:
+allow_subclassing_any = True
+
+[mypy-fuse]
+# fusepy has no type stubs:
+ignore_missing_imports = True
+
 [pylint.messages control]
 # Disable the message, report, category or checker with the given id(s). You
 # can either give multiple identifiers separated by comma (,) or put this
diff --git a/scripts/qmp/qom-fuse b/scripts/qmp/qom-fuse
index 0d11f731526..a5a7a304a3e 100755
--- a/scripts/qmp/qom-fuse
+++ b/scripts/qmp/qom-fuse
@@ -38,7 +38,14 @@ from errno import ENOENT, EPERM
 import os
 import stat
 import sys
-from typing import Dict
+from typing import (
+IO,
+Dict,
+Iterator,
+Mapping,
+Optional,
+Union,
+)
 
 import fuse
 from fuse import FUSE, FuseOSError, Operations
@@ -83,7 +90,7 @@ class QOMFuse(QOMCommand, Operations):
 self.fuse = FUSE(self, self.mount, foreground=True)
 return 0
 
-def get_ino(self, path):
+def get_ino(self, path: str) -> int:
 """Get an inode number for a given QOM path."""
 if path in self.ino_map:
 return self.ino_map[path]
@@ -91,7 +98,7 @@ class QOMFuse(QOMCommand, Operations):
 self.ino_count += 1
 return self.ino_map[path]
 
-def is_object(self, path):
+def is_object(self, path: str) -> bool:
 """Is the given QOM path an object?"""
 try:
 self.qom_list(path)
@@ -99,7 +106,7 @@ class QOMFuse(QOMCommand, Operations):
 except QMPResponseError:
 return False
 
-def is_property(self, path):
+def is_property(self, path: str) -> bool:
 """Is the given QOM path a property?"""
 path, prop = path.rsplit('/', 1)
 if path == '':
@@ -112,7 +119,7 @@ class QOMFuse(QOMCommand, Operations):
 except QMPResponseError:
 return False
 
-def is_link(self, path):
+def is_link(self, path: str) -> bool:
 """Is the given QOM path a link?"""
 path, prop = path.rsplit('/', 1)
 if path == '':
@@ -125,7 +132,7 @@ class QOMFuse(QOMCommand, Operations):
 except QMPResponseError:
 return False
 
-def read(self, path, size, offset, fh):
+def read(self, path: str, size: int, offset: int, fh: IO[bytes]) -> bytes:
 if not self.is_property(path):
 raise FuseOSError(ENOENT)
 
@@ -143,7 +150,7 @@ class QOMFuse(QOMCommand, Operations):
 
 return bytes(data[offset:][:size], encoding='utf-8')
 
-def readlink(self, path):
+def readlink(self, path: str) -> Union[bool, str]:
 if not self.is_link(path):
 return False
 path, prop = path.rsplit('/', 1)
@@ -151,7 +158,8 @@ class QOMFuse(QOMCommand, Operations):
 return prefix + str(self.qmp.command('qom-get', path=path,
  property=prop))
 
-def getattr(self, path, fh=None):
+def getattr(self, path: str,
+fh: Optional[IO[bytes]] = None) -> Mapping[str, object]:
 if self.is_link(path):
 value = {
 'st_mode': 0o755 | stat.S_IFLNK,
@@ -195,7 +203,7 @@ class QOMFuse(QOMCommand, Operations):
 raise FuseOSError(ENOENT)
 return value
 
-def readdir(self, path, fh):
+def readdir(self, path: str, fh: IO[bytes]) -> Iterator[str]:
 yield '.'
 yield '..'
 for item in self.qom_list(path):
-- 
2.31.1




[PATCH v3 04/19] python/qmp: Add qom script rewrites

2021-06-02 Thread John Snow
Inspired by qom-set, qom-get, qom-tree and qom-list; combine all four of
those scripts into a single script.

A later addition of qom-fuse as an 'extension' necessitates that some
common features are split out and shared between them.

Signed-off-by: John Snow 
---
 python/qemu/qmp/qom.py| 262 ++
 python/qemu/qmp/qom_common.py | 178 +++
 2 files changed, 440 insertions(+)
 create mode 100644 python/qemu/qmp/qom.py
 create mode 100644 python/qemu/qmp/qom_common.py

diff --git a/python/qemu/qmp/qom.py b/python/qemu/qmp/qom.py
new file mode 100644
index 000..7fe1448b5d9
--- /dev/null
+++ b/python/qemu/qmp/qom.py
@@ -0,0 +1,262 @@
+"""
+QEMU Object Model testing tools.
+
+usage: qom [-h] {set,get,list,tree} ...
+
+Query and manipulate QOM data
+
+optional arguments:
+  -h, --help   show this help message and exit
+
+QOM commands:
+  {set,get,list,tree}
+setSet a QOM property value
+getGet a QOM property value
+list   List QOM properties at a given path
+tree   Show QOM tree from a given path
+"""
+##
+# Copyright John Snow 2020, for Red Hat, Inc.
+# Copyright IBM, Corp. 2011
+#
+# Authors:
+#  John Snow 
+#  Anthony Liguori 
+#
+# This work is licensed under the terms of the GNU GPL, version 2 or later.
+# See the COPYING file in the top-level directory.
+#
+# Based on ./scripts/qmp/qom-[set|get|tree|list]
+##
+
+import argparse
+
+from . import QMPResponseError
+from .qom_common import QOMCommand
+
+
+class QOMSet(QOMCommand):
+"""
+QOM Command - Set a property to a given value.
+
+usage: qom-set [-h] [--socket SOCKET] . 
+
+Set a QOM property value
+
+positional arguments:
+  . QOM path and property, separated by a period '.'
+ new QOM property value
+
+optional arguments:
+  -h, --helpshow this help message and exit
+  --socket SOCKET, -s SOCKET
+QMP socket path or address (addr:port). May also be
+set via QMP_SOCKET environment variable.
+"""
+name = 'set'
+help = 'Set a QOM property value'
+
+@classmethod
+def configure_parser(cls, parser: argparse.ArgumentParser) -> None:
+super().configure_parser(parser)
+cls.add_path_prop_arg(parser)
+parser.add_argument(
+'value',
+metavar='',
+action='store',
+help='new QOM property value'
+)
+
+def __init__(self, args: argparse.Namespace):
+super().__init__(args)
+self.path, self.prop = args.path_prop.rsplit('.', 1)
+self.value = args.value
+
+def run(self) -> int:
+rsp = self.qmp.command(
+'qom-set',
+path=self.path,
+property=self.prop,
+value=self.value
+)
+print(rsp)
+return 0
+
+
+class QOMGet(QOMCommand):
+"""
+QOM Command - Get a property's current value.
+
+usage: qom-get [-h] [--socket SOCKET] .
+
+Get a QOM property value
+
+positional arguments:
+  . QOM path and property, separated by a period '.'
+
+optional arguments:
+  -h, --helpshow this help message and exit
+  --socket SOCKET, -s SOCKET
+QMP socket path or address (addr:port). May also be
+set via QMP_SOCKET environment variable.
+"""
+name = 'get'
+help = 'Get a QOM property value'
+
+@classmethod
+def configure_parser(cls, parser: argparse.ArgumentParser) -> None:
+super().configure_parser(parser)
+cls.add_path_prop_arg(parser)
+
+def __init__(self, args: argparse.Namespace):
+super().__init__(args)
+try:
+tmp = args.path_prop.rsplit('.', 1)
+except ValueError as err:
+raise ValueError('Invalid format for .') from err
+self.path = tmp[0]
+self.prop = tmp[1]
+
+def run(self) -> int:
+rsp = self.qmp.command(
+'qom-get',
+path=self.path,
+property=self.prop
+)
+if isinstance(rsp, dict):
+for key, value in rsp.items():
+print(f"{key}: {value}")
+else:
+print(rsp)
+return 0
+
+
+class QOMList(QOMCommand):
+"""
+QOM Command - List the properties at a given path.
+
+usage: qom-list [-h] [--socket SOCKET] 
+
+List QOM properties at a given path
+
+positional arguments:
+  QOM path
+
+optional arguments:
+  -h, --helpshow this help message and exit
+  --socket SOCKET, -s SOCKET
+QMP socket path or address (addr:port). May also be
+set via QMP_SOCKET environment variable.
+"""
+name = 'list'
+help = 'List QOM properties at a given path'
+
+@classmethod
+def 

[PATCH v3 06/19] scripts/qmp: redirect qom-xxx scripts to python/qemu/qmp/

2021-06-02 Thread John Snow
Redirect to the new qom scripts. These forwarders can be deleted
eventually when there has been more time for the dust on the Python
packaging to settle and people understand how to find these commands.

Note: You can run these by setting $PYTHONPATH in your shell and then
running "python3 -m qemu.qmp.qom", or you can install the qemu namespace
package and use the "qom" or "qom-set" scripts.

I've written how to install the package elsewhere, but for the sake of
git-blame, cd to ./python, and then do:

- pip3 install [--user] [-e] .

--user will install to your local user install (will not work inside of
  a venv), omitting this flag installs to your system-wide packages
  (outside of a venv) or to your current virtual environment (inside the
  venv).

  When installing to a venv or to your system-wide packages, "qom"
  should be in your $PATH already. If you do a user install, you may
  need to add ~/.local/bin to your $PATH if you haven't already.

-e installs in editable mode: the installed package is effectively just
 a symlink to this folder; so changes to your git working tree are
 reflected in the installed package.

Note: installing these packages to an environment outside a venv can be
dangerous: Many QEMU scripts will begin to prefer the installed version
instead of the version directly in the tree. Use with caution. editable
mode is recommended when working outside of a venv.

Signed-off-by: John Snow 
Reviewed-by: Philippe Mathieu-Daudé 
---
 scripts/qmp/qom-get  | 66 +++
 scripts/qmp/qom-list | 63 +++--
 scripts/qmp/qom-set  | 63 +++--
 scripts/qmp/qom-tree | 74 +++-
 4 files changed, 16 insertions(+), 250 deletions(-)

diff --git a/scripts/qmp/qom-get b/scripts/qmp/qom-get
index 666df718320..e4f3e0c0138 100755
--- a/scripts/qmp/qom-get
+++ b/scripts/qmp/qom-get
@@ -1,69 +1,11 @@
 #!/usr/bin/env python3
-##
-# QEMU Object Model test tools
-#
-# Copyright IBM, Corp. 2011
-#
-# Authors:
-#  Anthony Liguori   
-#
-# This work is licensed under the terms of the GNU GPL, version 2 or later.  
See
-# the COPYING file in the top-level directory.
-##
 
-import sys
 import os
+import sys
 
 sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..', 'python'))
-from qemu.qmp import QEMUMonitorProtocol
+from qemu.qmp.qom import QOMGet
 
-cmd, args = sys.argv[0], sys.argv[1:]
-socket_path = None
-path = None
-prop = None
 
-def usage():
-return '''environment variables:
-QMP_SOCKET=
-usage:
-%s [-h] [-s ] .
-''' % cmd
-
-def usage_error(error_msg = "unspecified error"):
-sys.stderr.write('%s\nERROR: %s\n' % (usage(), error_msg))
-exit(1)
-
-if len(args) > 0:
-if args[0] == "-h":
-print(usage())
-exit(0);
-elif args[0] == "-s":
-try:
-socket_path = args[1]
-except:
-usage_error("missing argument: QMP socket path or address");
-args = args[2:]
-
-if not socket_path:
-if 'QMP_SOCKET' in os.environ:
-socket_path = os.environ['QMP_SOCKET']
-else:
-usage_error("no QMP socket path or address given");
-
-if len(args) > 0:
-try:
-path, prop = args[0].rsplit('.', 1)
-except:
-usage_error("invalid format for path/property/value")
-else:
-usage_error("not enough arguments")
-
-srv = QEMUMonitorProtocol(socket_path)
-srv.connect()
-
-rsp = srv.command('qom-get', path=path, property=prop)
-if type(rsp) == dict:
-for i in rsp.keys():
-print('%s: %s' % (i, rsp[i]))
-else:
-print(rsp)
+if __name__ == '__main__':
+sys.exit(QOMGet.entry_point())
diff --git a/scripts/qmp/qom-list b/scripts/qmp/qom-list
index 5074fd939f4..7a071a54e1e 100755
--- a/scripts/qmp/qom-list
+++ b/scripts/qmp/qom-list
@@ -1,66 +1,11 @@
 #!/usr/bin/env python3
-##
-# QEMU Object Model test tools
-#
-# Copyright IBM, Corp. 2011
-#
-# Authors:
-#  Anthony Liguori   
-#
-# This work is licensed under the terms of the GNU GPL, version 2 or later.  
See
-# the COPYING file in the top-level directory.
-##
 
-import sys
 import os
+import sys
 
 sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..', 'python'))
-from qemu.qmp import QEMUMonitorProtocol
+from qemu.qmp.qom import QOMList
 
-cmd, args = sys.argv[0], sys.argv[1:]
-socket_path = None
-path = None
-prop = None
 
-def usage():
-return '''environment variables:
-QMP_SOCKET=
-usage:
-%s [-h] [-s ] []
-''' % cmd
-
-def usage_error(error_msg = "unspecified error"):
-sys.stderr.write('%s\nERROR: %s\n' % (usage(), error_msg))
-exit(1)
-
-if len(args) > 0:
-if args[0] == "-h":
-print(usage())
-exit(0);
-elif args[0] == "-s":
-try:
-socket_path = args[1]
-except:
-usage_error("missing argument: QMP socket path or address");
-args = args[2:]
-
-if not socket_path:
-if 'QMP_SOCKET' in 

[PATCH v3 00/19] Python: move /scripts/qmp/qom* to /python/qemu/qmp/qom*

2021-06-02 Thread John Snow
Closes: https://gitlab.com/qemu-project/qemu/-/issues/202
GitLab: https://gitlab.com/jsnow/qemu/-/commits/python-package-qom
CI: https://gitlab.com/jsnow/qemu/-/pipelines/313932818

Hello!
--

This series applies the usual linting cleanups to modernize the qom
tools and then integrates them into the python packaging hierarchy.

This will help prevent further bitrot of these tools.

I don't expect or need a detailed review of the QOM tools themselves --
these tools are not used during build OR testing, and some are fairly
bitrotted in places.

However, some details of how the python packaging system is being
utilized here may attract your attention and could be worth a look.
(Patches 5-6 and 16-19 are the interesting ones.)

Since these scripts aren't critical, I'm OK with sending a fairly hasty
PR to merge these sooner rather than later.

Overview:
-

Patch 1: Update Pipfile.lock (See the commit as for why ...)

Patches 2-3: Correct some existing typing issues in qemu.qmp

Patch 4: Combine qom-set, qom-get, (etc) into one, newly written script
that makes all of the command invocations, help text, etc. consistent.
(I ask that review for this patch should be limited to critical
mistakes: I have no interest in developing the QOM tools further.)

Patches 5-6: Integrate the qom tools into the python package.

Patches 7-15: Delinting of the qom_fuse script. Similarly, I am not
terribly interested in further improvements here, personally.

Patches 16-19: Integrating qom-fuse into the Python packaging directory;
additional care is taken to ensure that "optional" dependencies like
fusepy are handled well.

Changelog
-

V3:
- Technically, I sent two versions of this before, a long time ago.
  This has been cleaned up and based on the latest origin/master.

John Snow (19):
  python/pipenv: Update Pipfile.lock
  python/qmp: Fix type of SocketAddrT
  python/qmp: add parse_address classmethod
  python/qmp: Add qom script rewrites
  python/qmp: add qom script entry points
  scripts/qmp: redirect qom-xxx scripts to python/qemu/qmp/
  scripts/qom-fuse: apply isort rules
  scripts/qom-fuse: apply flake8 rules
  python: Add 'fh' to known-good variable names
  scripts/qom-fuse: Apply pylint rules
  scripts/qom-fuse: Add docstrings
  scripts/qom-fuse: Convert to QOMCommand
  scripts/qom-fuse: use QOMCommand.qom_list()
  scripts/qom-fuse: ensure QOMFuse.read always returns bytes
  scripts/qom-fuse: add static type hints
  python: add optional FUSE dependencies
  scripts/qom-fuse: move to python/qemu/qmp/qom_fuse.py
  scripts/qom-fuse: add redirection shim to python/qemu/qmp/qom-fuse.py
  python/qmp: add fuse command to 'qom' tools

 python/Pipfile.lock   |  97 +++-
 python/qemu/qmp/__init__.py   |  28 +++-
 python/qemu/qmp/qom.py| 272 ++
 python/qemu/qmp/qom_common.py | 178 ++
 python/qemu/qmp/qom_fuse.py   | 206 +
 python/setup.cfg  |  33 -
 scripts/qmp/qmp-shell |  21 +--
 scripts/qmp/qom-fuse  | 144 +-
 scripts/qmp/qom-get   |  66 +
 scripts/qmp/qom-list  |  63 +---
 scripts/qmp/qom-set   |  63 +---
 scripts/qmp/qom-tree  |  74 +
 12 files changed, 828 insertions(+), 417 deletions(-)
 create mode 100644 python/qemu/qmp/qom.py
 create mode 100644 python/qemu/qmp/qom_common.py
 create mode 100644 python/qemu/qmp/qom_fuse.py

-- 
2.31.1





[PATCH v3 12/19] scripts/qom-fuse: Convert to QOMCommand

2021-06-02 Thread John Snow
Move qom-fuse onto the QOMCommand base established in
python/qemu/qmp/qom_common.py. The interface doesn't change
incompatibly, "qom-fuse mountpoint" still works as an invocation, and
QMP_SOCKET is still used as the environment variable.

Signed-off-by: John Snow 
---
 scripts/qmp/qom-fuse | 59 ++--
 1 file changed, 46 insertions(+), 13 deletions(-)

diff --git a/scripts/qmp/qom-fuse b/scripts/qmp/qom-fuse
index 1fb3008a167..1676fb78d99 100755
--- a/scripts/qmp/qom-fuse
+++ b/scripts/qmp/qom-fuse
@@ -7,11 +7,19 @@ may be browsed, queried and edited using traditional shell 
tooling.
 
 This script requires the 'fusepy' python package.
 
-ENV:
-QMP_SOCKET: Path to the QMP server socket
 
-Usage:
-qom-fuse /mount/to/here
+usage: qom-fuse [-h] [--socket SOCKET] 
+
+Mount a QOM tree as a FUSE filesystem
+
+positional arguments:
+ Mount point
+
+optional arguments:
+  -h, --helpshow this help message and exit
+  --socket SOCKET, -s SOCKET
+QMP socket path or address (addr:port). May also be
+set via QMP_SOCKET environment variable.
 """
 ##
 # Copyright IBM, Corp. 2012
@@ -25,30 +33,56 @@ Usage:
 # See the COPYING file in the top-level directory.
 ##
 
+import argparse
 from errno import ENOENT, EPERM
 import os
 import stat
 import sys
+from typing import Dict
 
 import fuse
 from fuse import FUSE, FuseOSError, Operations
 
 
 sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..', 'python'))
-from qemu.qmp import QEMUMonitorProtocol, QMPResponseError
+from qemu.qmp import QMPResponseError
+from qemu.qmp.qom_common import QOMCommand
 
 
 fuse.fuse_python_api = (0, 2)
 
 
-class QOMFS(Operations):
-"""QOMFS implements fuse.Operations to provide a QOM filesystem."""
-def __init__(self, qmp):
-self.qmp = qmp
-self.qmp.connect()
-self.ino_map = {}
+class QOMFuse(QOMCommand, Operations):
+"""
+QOMFuse implements both fuse.Operations and QOMCommand.
+
+Operations implements the FS, and QOMCommand implements the CLI command.
+"""
+name = 'fuse'
+help = 'Mount a QOM tree as a FUSE filesystem'
+fuse: FUSE
+
+@classmethod
+def configure_parser(cls, parser: argparse.ArgumentParser) -> None:
+super().configure_parser(parser)
+parser.add_argument(
+'mount',
+metavar='',
+action='store',
+help="Mount point",
+)
+
+def __init__(self, args: argparse.Namespace):
+super().__init__(args)
+self.mount = args.mount
+self.ino_map: Dict[str, int] = {}
 self.ino_count = 1
 
+def run(self) -> int:
+print(f"Mounting QOMFS to '{self.mount}'", file=sys.stderr)
+self.fuse = FUSE(self, self.mount, foreground=True)
+return 0
+
 def get_ino(self, path):
 """Get an inode number for a given QOM path."""
 if path in self.ino_map:
@@ -171,5 +205,4 @@ class QOMFS(Operations):
 
 
 if __name__ == '__main__':
-fuse = FUSE(QOMFS(QEMUMonitorProtocol(os.environ['QMP_SOCKET'])),
-sys.argv[1], foreground=True)
+sys.exit(QOMFuse.entry_point())
-- 
2.31.1




[PATCH v3 05/19] python/qmp: add qom script entry points

2021-06-02 Thread John Snow
Add the 'qom', 'qom-set', 'qom-get', 'qom-list', and 'qom-tree' scripts
to the qemu.qmp package. When you install this package, these scripts
will become available on your command line.

(e.g. when inside of a venv, `cd python && pip install .` will add
'qom', 'qom-set', etc to your $PATH.)

Signed-off-by: John Snow 
Reviewed-by: Philippe Mathieu-Daudé 
---
 python/setup.cfg | 8 
 1 file changed, 8 insertions(+)

diff --git a/python/setup.cfg b/python/setup.cfg
index 0fcdec6f322..a19029d5388 100644
--- a/python/setup.cfg
+++ b/python/setup.cfg
@@ -37,6 +37,14 @@ devel =
 pylint >= 2.8.0
 tox >= 3.18.0
 
+[options.entry_points]
+console_scripts =
+qom = qemu.qmp.qom:main
+qom-set = qemu.qmp.qom:QOMSet.entry_point
+qom-get = qemu.qmp.qom:QOMGet.entry_point
+qom-list = qemu.qmp.qom:QOMList.entry_point
+qom-tree = qemu.qmp.qom:QOMTree.entry_point
+
 [flake8]
 extend-ignore = E722  # Prefer pylint's bare-except checks to flake8's
 exclude = __pycache__,
-- 
2.31.1




[PATCH v3 03/19] python/qmp: add parse_address classmethod

2021-06-02 Thread John Snow
This takes the place of qmp-shell's __get_address function. It also
allows other utilities to share the same parser and syntax for
specifying QMP locations.

Signed-off-by: John Snow 
---
 python/qemu/qmp/__init__.py | 26 ++
 scripts/qmp/qmp-shell   | 21 ++---
 2 files changed, 28 insertions(+), 19 deletions(-)

diff --git a/python/qemu/qmp/__init__.py b/python/qemu/qmp/__init__.py
index 5fb970f8a80..822c793c320 100644
--- a/python/qemu/qmp/__init__.py
+++ b/python/qemu/qmp/__init__.py
@@ -92,6 +92,12 @@ def __init__(self, reply: QMPMessage):
 self.reply = reply
 
 
+class QMPBadPortError(QMPError):
+"""
+Unable to parse socket address: Port was non-numerical.
+"""
+
+
 class QEMUMonitorProtocol:
 """
 Provide an API to connect to QEMU via QEMU Monitor Protocol (QMP) and then
@@ -219,6 +225,26 @@ def __exit__(self,
 # Implement context manager exit function.
 self.close()
 
+@classmethod
+def parse_address(cls, address: str) -> SocketAddrT:
+"""
+Parse a string into a QMP address.
+
+Figure out if the argument is in the port:host form.
+If it's not, it's probably a file path.
+"""
+components = address.split(':')
+if len(components) == 2:
+try:
+port = int(components[1])
+except ValueError:
+msg = f"Bad port: '{components[1]}' in '{address}'."
+raise QMPBadPortError(msg) from None
+return (components[0], port)
+
+# Treat as filepath.
+return address
+
 def connect(self, negotiate: bool = True) -> Optional[QMPMessage]:
 """
 Connect to the QMP Monitor and perform capabilities negotiation.
diff --git a/scripts/qmp/qmp-shell b/scripts/qmp/qmp-shell
index b4d06096abd..d5ae8a9b212 100755
--- a/scripts/qmp/qmp-shell
+++ b/scripts/qmp/qmp-shell
@@ -89,8 +89,6 @@ class QMPCompleter(list):
 class QMPShellError(Exception):
 pass
 
-class QMPShellBadPort(QMPShellError):
-pass
 
 class FuzzyJSON(ast.NodeTransformer):
 '''This extension of ast.NodeTransformer filters literal "true/false/null"
@@ -109,7 +107,7 @@ class FuzzyJSON(ast.NodeTransformer):
 #   _execute_cmd()). Let's design a better one.
 class QMPShell(qmp.QEMUMonitorProtocol):
 def __init__(self, address, pretty=False):
-super(QMPShell, self).__init__(self.__get_address(address))
+super(QMPShell, self).__init__(self.parse_address(address))
 self._greeting = None
 self._completer = None
 self._pretty = pretty
@@ -118,21 +116,6 @@ class QMPShell(qmp.QEMUMonitorProtocol):
 self._histfile = os.path.join(os.path.expanduser('~'),
   '.qmp-shell_history')
 
-def __get_address(self, arg):
-"""
-Figure out if the argument is in the port:host form, if it's not it's
-probably a file path.
-"""
-addr = arg.split(':')
-if len(addr) == 2:
-try:
-port = int(addr[1])
-except ValueError:
-raise QMPShellBadPort
-return ( addr[0], port )
-# socket path
-return arg
-
 def _fill_completion(self):
 cmds = self.cmd('query-commands')
 if 'error' in cmds:
@@ -437,7 +420,7 @@ def main():
 
 if qemu is None:
 fail_cmdline()
-except QMPShellBadPort:
+except qmp.QMPBadPortError:
 die('bad port number in command-line')
 
 try:
-- 
2.31.1




[PATCH v3 10/19] scripts/qom-fuse: Apply pylint rules

2021-06-02 Thread John Snow
- Catch specific exceptions from QMP
- Reraise errors with explicit context
- method parameters should match parent's names

Signed-off-by: John Snow 
Reviewed-by: Philippe Mathieu-Daudé 
---
 scripts/qmp/qom-fuse | 16 
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/scripts/qmp/qom-fuse b/scripts/qmp/qom-fuse
index ca30e928679..805e99c8ecd 100755
--- a/scripts/qmp/qom-fuse
+++ b/scripts/qmp/qom-fuse
@@ -23,7 +23,7 @@ from fuse import FUSE, FuseOSError, Operations
 
 
 sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..', 'python'))
-from qemu.qmp import QEMUMonitorProtocol
+from qemu.qmp import QEMUMonitorProtocol, QMPResponseError
 
 
 fuse.fuse_python_api = (0, 2)
@@ -47,7 +47,7 @@ class QOMFS(Operations):
 try:
 self.qmp.command('qom-list', path=path)
 return True
-except:
+except QMPResponseError:
 return False
 
 def is_property(self, path):
@@ -59,7 +59,7 @@ class QOMFS(Operations):
 if item['name'] == prop:
 return True
 return False
-except:
+except QMPResponseError:
 return False
 
 def is_link(self, path):
@@ -73,10 +73,10 @@ class QOMFS(Operations):
 return True
 return False
 return False
-except:
+except QMPResponseError:
 return False
 
-def read(self, path, length, offset, fh):
+def read(self, path, size, offset, fh):
 if not self.is_property(path):
 return -ENOENT
 
@@ -86,13 +86,13 @@ class QOMFS(Operations):
 try:
 data = self.qmp.command('qom-get', path=path, property=prop)
 data += '\n'  # make values shell friendly
-except:
-raise FuseOSError(EPERM)
+except QMPResponseError as err:
+raise FuseOSError(EPERM) from err
 
 if offset > len(data):
 return ''
 
-return bytes(data[offset:][:length], encoding='utf-8')
+return bytes(data[offset:][:size], encoding='utf-8')
 
 def readlink(self, path):
 if not self.is_link(path):
-- 
2.31.1




[PATCH v3 02/19] python/qmp: Fix type of SocketAddrT

2021-06-02 Thread John Snow
In porting the qom tools, qmp-shell, etc; it becomes evident that this
type is wrong.

This is an integer, not a string. We didn't catch this before because
none of QEMUMonitorProtocol's *users* happen to be checked, and the
internal logic of this class is otherwise self-consistent. Additionally,
mypy was not introspecting into the socket() interface to realize we
were passing a bad type for AF_INET. Fixed now.

Signed-off-by: John Snow 
---
 python/qemu/qmp/__init__.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/python/qemu/qmp/__init__.py b/python/qemu/qmp/__init__.py
index 9606248a3d2..5fb970f8a80 100644
--- a/python/qemu/qmp/__init__.py
+++ b/python/qemu/qmp/__init__.py
@@ -44,7 +44,7 @@
 QMPMessage = Dict[str, Any]
 QMPReturnValue = Dict[str, Any]
 
-InternetAddrT = Tuple[str, str]
+InternetAddrT = Tuple[str, int]
 UnixAddrT = str
 SocketAddrT = Union[InternetAddrT, UnixAddrT]
 
-- 
2.31.1




[PATCH v3 01/19] python/pipenv: Update Pipfile.lock

2021-06-02 Thread John Snow
In a previous commit, I added tox to the development requirements of the
Python library. I never bothered to add them to the Pipfile, because
they aren't needed there. Here, I sync it anyway in its own commit so
that when we add new packages later that the diffstats will not
confusingly appear to pull in lots of extra packages.

Ideally I could tell Pipenv simply not to install these, but it doesn't
seem to support that, exactly. The alternative is removing Tox from the
development requires, which I'd rather not do.

The other alternative is re-specifying all of the dependencies of
setup.cfg in the Pipfile, which I'd also rather not do.

Picking what feels least-worst here.

Signed-off-by: John Snow 
---
 python/Pipfile.lock | 91 +++--
 1 file changed, 88 insertions(+), 3 deletions(-)

diff --git a/python/Pipfile.lock b/python/Pipfile.lock
index 6e344f5fadf..f2a3f91d0fa 100644
--- a/python/Pipfile.lock
+++ b/python/Pipfile.lock
@@ -22,6 +22,13 @@
 }
 },
 "develop": {
+"appdirs": {
+"hashes": [
+
"sha256:7d5d0167b2b1ba821647616af46a749d1c653740dd0d2415100fe26e27afdf41",
+
"sha256:a841dacd6b99318a741b166adb07e19ee71a274450e68237b4650ca1055ab128"
+],
+"version": "==1.4.4"
+},
 "astroid": {
 "hashes": [
 
"sha256:4db03ab5fc3340cf619dbc25e42c2cc3755154ce6009469766d7143d1fc2ee4e",
@@ -38,6 +45,20 @@
 "markers": "python_version >= '3.6'",
 "version": "==88.1"
 },
+"distlib": {
+"hashes": [
+
"sha256:106fef6dc37dd8c0e2c0a60d3fca3e77460a48907f335fa28420463a6f799736",
+
"sha256:23e223426b28491b1ced97dc3bbe183027419dfc7982b4fa2f05d5f3ff10711c"
+],
+"version": "==0.3.2"
+},
+"filelock": {
+"hashes": [
+
"sha256:18d82244ee114f543149c66a6e0c14e9c4f8a1044b5cdaadd0f82159d6a6ff59",
+
"sha256:929b7d63ec5b7d6b71b0fa5ac14e030b3f70b75747cef1b10da9b879fef15836"
+],
+"version": "==3.0.12"
+},
 "flake8": {
 "hashes": [
 
"sha256:07528381786f2a6237b061f6e96610a4167b226cb926e2aa2b6b1d78057c576b",
@@ -54,6 +75,14 @@
 "markers": "python_version < '3.8'",
 "version": "==4.0.1"
 },
+"importlib-resources": {
+"hashes": [
+
"sha256:54161657e8ffc76596c4ede7080ca68cb02962a2e074a2586b695a93a925d36e",
+
"sha256:e962bff7440364183203d179d7ae9ad90cb1f2b74dcb84300e88ecc42dca3351"
+],
+"markers": "python_version < '3.7'",
+"version": "==5.1.4"
+},
 "isort": {
 "hashes": [
 
"sha256:0a943902919f65c5684ac4e0154b1ad4fac6dcaa5d9f3426b732f1c8b5419be6",
@@ -132,6 +161,30 @@
 ],
 "version": "==0.4.3"
 },
+"packaging": {
+"hashes": [
+
"sha256:5b327ac1320dc863dca72f4514ecc086f31186744b84a230374cc1fd776feae5",
+
"sha256:67714da7f7bc052e064859c05c595155bd1ee9f69f76557e21f051443c20947a"
+],
+"markers": "python_version >= '2.7' and python_version not in 
'3.0, 3.1, 3.2, 3.3'",
+"version": "==20.9"
+},
+"pluggy": {
+"hashes": [
+
"sha256:15b2acde666561e1298d71b523007ed7364de07029219b604cf808bfa1c765b0",
+
"sha256:966c145cd83c96502c3c3868f50408687b38434af77734af1e9ca461a4081d2d"
+],
+"markers": "python_version >= '2.7' and python_version not in 
'3.0, 3.1, 3.2, 3.3'",
+"version": "==0.13.1"
+},
+"py": {
+"hashes": [
+
"sha256:21b81bda15b66ef5e1a777a21c4dcd9c20ad3efd0b3f817e7a809035269e1bd3",
+
"sha256:3b80836aa6d1feeaa108e046da6423ab8f6ceda6468545ae8d02d9d58d18818a"
+],
+"markers": "python_version >= '2.7' and python_version not in 
'3.0, 3.1, 3.2, 3.3'",
+"version": "==1.10.0"
+},
 "pycodestyle": {
 "hashes": [
 
"sha256:514f76d918fcc0b55c6680472f0a37970994e07bbb80725808c17089be302068",
@@ -156,18 +209,42 @@
 "markers": "python_version ~= '3.6'",
 "version": "==2.8.2"
 },
+"pyparsing": {
+"hashes": [
+
"sha256:c203ec8783bf771a155b207279b9bccb8dea02d8f0c9e5f8ead507bc3246ecc1",
+
"sha256:ef9d7589ef3c200abe66653d3f1ab1033c3c419ae9b9bdb1240a85b024efc88b"
+],
+"markers": "python_version >= '2.6' and python_version not in 
'3.0, 3.1, 3.2, 3.3'",
+"version": "==2.4.7"
+},
 "qemu": {
 "editable": true,
 "path": "."
 },
+"six": {
+"hashes": [
+

[PATCH v3 0/2] Gitlab: Add issue templates

2021-06-02 Thread John Snow
Add "Bug" and "Feature Request" templates to the Gitlab interface to
help improve the quality of newly reported issues.

To see what this looks like, I've temporarily allowed my Gitlab fork to
diverge with these files merged.  See my fork's "new issue" page to see
it in action: https://gitlab.com/jsnow/qemu/-/issues/new?issue

These patches do not add a "default" template, the user still has to
select one from the list. I recommend that someone with permissions
updates the default template:

1. https://gitlab.com/qemu-project/qemu/edit
2. ctrl+f "Default description template for issues"
3. Update the default to the (suggested) below:

```

```

We can use this cover letter to discuss/review the wording on that
default template which exists outside of repository data.

V3:
 - Add pointer to https://www.qemu.org/download/#source
 - Add pointer to https://www.qemu.org/contribute/security-process/
 - Remove blurb covering tracing instructions.

V2:
- Updated both templates based on feedback from Peter, Daniel, and
  Thomas.

John Snow (2):
  GitLab: Add "Bug" issue reporting template
  GitLab: Add "Feature Request" issue template.

 .gitlab/issue_templates/bug.md | 63 ++
 .gitlab/issue_templates/feature_request.md | 32 +++
 2 files changed, 95 insertions(+)
 create mode 100644 .gitlab/issue_templates/bug.md
 create mode 100644 .gitlab/issue_templates/feature_request.md

-- 
2.31.1





[PATCH v3 2/2] GitLab: Add "Feature Request" issue template.

2021-06-02 Thread John Snow
Based on Peter Krempa's libvirt template, feature.md.

CC: Peter Krempa 
Signed-off-by: John Snow 
Reviewed-by: Stefan Hajnoczi 
---
 .gitlab/issue_templates/feature_request.md | 32 ++
 1 file changed, 32 insertions(+)
 create mode 100644 .gitlab/issue_templates/feature_request.md

diff --git a/.gitlab/issue_templates/feature_request.md 
b/.gitlab/issue_templates/feature_request.md
new file mode 100644
index 000..fc58ca27634
--- /dev/null
+++ b/.gitlab/issue_templates/feature_request.md
@@ -0,0 +1,32 @@
+
+
+## Goal
+
+
+
+## Technical details
+
+
+
+## Additional information
+
+
+
+/label ~"kind::Feature Request"
-- 
2.31.1




[PATCH v3 1/2] GitLab: Add "Bug" issue reporting template

2021-06-02 Thread John Snow
Based loosely on libvirt's template, written by Peter Krempa.

CC: Peter Krempa 
Signed-off-by: John Snow 
---
 .gitlab/issue_templates/bug.md | 63 ++
 1 file changed, 63 insertions(+)
 create mode 100644 .gitlab/issue_templates/bug.md

diff --git a/.gitlab/issue_templates/bug.md b/.gitlab/issue_templates/bug.md
new file mode 100644
index 000..9445777252b
--- /dev/null
+++ b/.gitlab/issue_templates/bug.md
@@ -0,0 +1,63 @@
+
+
+## Host environment
+ - Operating system: (Windows 10 21H1, Fedora 34, etc.)
+ - OS/kernel version: (For POSIX hosts, use `uname -a`)
+ - Architecture: (x86, ARM, s390x, etc.)
+ - QEMU flavor: (qemu-system-x86_64, qemu-aarch64, qemu-img, etc.)
+ - QEMU version: (e.g. `qemu-system-x86_64 --version`)
+ - QEMU command line:
+   
+   ```
+   ./qemu-system-x86_64 -M q35 -m 4096 -enable-kvm -hda fedora32.qcow2
+   ```
+
+## Emulated/Virtualized environment
+ - Operating system: (Windows 10 21H1, Fedora 34, etc.)
+ - OS/kernel version: (For POSIX guests, use `uname -a`.)
+ - Architecture: (x86, ARM, s390x, etc.)
+
+
+## Description of problem
+
+
+
+## Steps to reproduce
+1.
+2.
+3.
+
+
+## Additional information
+
+
+
+
+/label ~"kind::Bug"
-- 
2.31.1




Re: [PATCH v4 26/35] python/qemu/machine: QEMUMachine: improve qmp() method

2021-06-02 Thread John Snow

On 6/2/21 9:10 AM, Vladimir Sementsov-Ogievskiy wrote:

We often call qmp() with unpacking dict, like qmp('foo', **{...}).
mypy don't really like it, it thinks that passed unpacked dict is a
positional argument and complains that it type should be bool (because
second argument of qmp() is conv_keys: bool).

Allow passing dict directly, simplifying interface, and giving a way to
satisfy mypy.

Signed-off-by: Vladimir Sementsov-Ogievskiy 
Reviewed-by: Max Reitz 
---
  python/qemu/machine.py | 12 +++-
  1 file changed, 11 insertions(+), 1 deletion(-)

diff --git a/python/qemu/machine.py b/python/qemu/machine.py
index ff35f2cd6c..7a14605040 100644
--- a/python/qemu/machine.py
+++ b/python/qemu/machine.py
@@ -549,11 +549,21 @@ def _qmp_args(cls, conv_keys: bool,
  return args
  
  def qmp(self, cmd: str,

-conv_keys: bool = True,
+args_dict: Optional[Dict[str, Any]] = None,


try using object here, too.


+conv_keys: Optional[bool] = None,
  **args: Any) -> QMPMessage:
  """
  Invoke a QMP command and return the response dict
  """
+if args_dict is not None:
+assert not args
+assert conv_keys is None
+args = args_dict
+conv_keys = False
+
+if conv_keys is None:
+conv_keys = True
+
  qmp_args = self._qmp_args(conv_keys, args)
  return self._qmp.cmd(cmd, args=qmp_args)
  



With the comment addressed:

Reviewed-by: John Snow 

Thanks,
--js




Re: [PATCH v4 25/35] python/qemu/machine.py: refactor _qemu_args()

2021-06-02 Thread John Snow

On 6/2/21 9:10 AM, Vladimir Sementsov-Ogievskiy wrote:

  - use shorter construction
  - don't create new dict if not needed
  - drop extra unpacking key-val arguments
  - drop extra default values

Signed-off-by: Vladimir Sementsov-Ogievskiy 
Reviewed-by: Max Reitz 


Sorry, I shuffled around the Python stuff and this doesn't apply 
anymore. I have applied it myself for review, though.


(I don't anticipate any more major shake-ups from this point forward. 
Thanks for your help on reviews for that series.)



---
  python/qemu/machine.py | 18 --
  1 file changed, 8 insertions(+), 10 deletions(-)

diff --git a/python/qemu/machine.py b/python/qemu/machine.py
index 6e44bda337..ff35f2cd6c 100644
--- a/python/qemu/machine.py
+++ b/python/qemu/machine.py
@@ -541,14 +541,12 @@ def _qmp(self) -> qmp.QEMUMonitorProtocol:
  return self._qmp_connection
  
  @classmethod

-def _qmp_args(cls, _conv_keys: bool = True, **args: Any) -> Dict[str, Any]:
-qmp_args = dict()
-for key, value in args.items():
-if _conv_keys:
-qmp_args[key.replace('_', '-')] = value
-else:
-qmp_args[key] = value
-return qmp_args
+def _qmp_args(cls, conv_keys: bool,
+  args: Dict[str, Any]) -> Dict[str, Any]:
+if conv_keys:
+return {k.replace('_', '-'): v for k, v in args.items()}
+else:
+return args


qemu/machine/machine.py:558:8: R1705: Unnecessary "else" after "return" 
(no-else-return)


Also, can you try using Dict[str, object] instead? This keeps stricter 
type checking enabled for callers trying to utilize the return value. On 
my review branch (based on master, not kwolf's staging branch) it passes 
Python linting and iotests 297, so it should hopefully not be a hassle.


  
  def qmp(self, cmd: str,

  conv_keys: bool = True,
@@ -556,7 +554,7 @@ def qmp(self, cmd: str,
  """
  Invoke a QMP command and return the response dict
  """
-qmp_args = self._qmp_args(conv_keys, **args)
+qmp_args = self._qmp_args(conv_keys, args)
  return self._qmp.cmd(cmd, args=qmp_args)
  
  def command(self, cmd: str,

@@ -567,7 +565,7 @@ def command(self, cmd: str,
  On success return the response dict.
  On failure raise an exception.
  """
-qmp_args = self._qmp_args(conv_keys, **args)
+qmp_args = self._qmp_args(conv_keys, args)
  return self._qmp.command(cmd, **qmp_args)
  
  def get_qmp_event(self, wait: bool = False) -> Optional[QMPMessage]:




With those items addressed:

Reviewed-by: John Snow 




Re: [PATCH qemu] Add basic power management to raspi.

2021-06-02 Thread Nolan

On 6/2/21 4:22 PM, Philippe Mathieu-Daudé wrote:

On 6/2/21 11:33 PM, Nolan wrote:

On 5/31/21 4:23 AM, Philippe Mathieu-Daudé wrote:

Hi Nolan,

Thanks for your patch!

There is something odd with your email address, which apparently
became source...@sigbus.net instead of no...@sigbus.net.


Ugh, oops. I was trying out sourcehut for this, and reflexively gave
them a marker email. I'm pretty sure sourcehut won't sell my email
address, so I'll just change it.


On 5/18/21 10:24 PM, ~nolanl wrote:

From: Nolan Leake 

This is just enough to make reboot and poweroff work.


Please precise "for Linux kernels", since this doesn't work
with firmwares (ideally we should implement the FIRMWARE_NOTIFY_REBOOT
property - which Linux sends - to handle the machine reboot/halt
via the videocore firmware model).


Thanks, good point re: this being tuned to what Linux (and u-boot) do.
Poking around a bit, it looks like
"trusted-firmware-a"/"arm-trusted-firmware" uses the same method, as do
a couple of bare-metal/hobby OSes. Couldn't immediately figure out what
FreeBSD does.

I'm not sure I understand your point about FIRMWARE_NOTIFY_REBOOT, my
understanding is that message is there to tell the GPU firmware that
we're about to reboot, so it can do things like reload the PCIe USB
chip's firmware. In my testing without the watchdog module loaded, my
physical pi4 does not reboot, so it appears that sending
FIRMWARE_NOTIFY_REBOOT is not enough on its own.


 From the ARM core point of view, once it sent the FIRMWARE_NOTIFY_REBOOT
message, it can't really power-off itself, it waits in a busy loop for
the VC to disable its power domain.

hw/misc/bcm2835_property.c is our model of the VC behavior. IMO this
should be where QEMU shuts down. How I'd model it is:

- ARM: sends FIRMWARE_NOTIFY_REBOOT and loops

- VC emulated via property: delays (200ms?) then calls
   SHUTDOWN_CAUSE_GUEST_RESET.

(it helps to see hw/misc/bcm2835_property.c as an external component).


This is not what I see on my hardware pi4. With the following kernel config:
...
CONFIG_RASPBERRYPI_FIRMWARE=y
...
CONFIG_BCM2835_WDT=m
...

if I reboot the machine without the WDT module (but with the firmware 
module), I get this:

#  echo b > /proc/sysrq-trigger
[   54.498768] sysrq: Resetting
[   54.501713] SMP: stopping secondary CPUs
[   54.505701] Reboot failed -- System halted

and it hangs forever there.

If I load the WDT module, it reboots successfully.


qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN);
+    } else {
+    qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
+    }
+    }


Shouldn't we log the unsupported bits?


I can add that, I didn't originally because the unsupported writes are
expected.


I'd prefer we log them, even if unsupported, so in case something
behaves oddly we could look at those bits.


In v2, I log the writes, since any side effects they have (notably the 
watchdog register) are unimplemented. I didn't log the reads, since they 
actually behave exactly as the real hardware does...



+static void bcm2835_powermgt_reset(DeviceState *dev)
+{
+    BCM2835PowerMgtState *s = BCM2835_POWERMGT(dev);
+
+    s->rstc = 0x0102;
+    s->rsts = 0x1000;
+    s->wdog = 0x;


Where these bits come from?


 From my pi4. https://elinux.org/BCM2835_registers agrees (processed from
Broadcom source code).


OK, so please add a comment referring to
https://elinux.org/BCM2835_registers#PM.

Looking forward for v2 :)


Already sent. Is the link comment here worth a v3?




Re: [PATCH v8 02/12] accel: Introduce 'query-accels' QMP command

2021-06-02 Thread John Snow

On 5/26/21 1:04 PM, Philippe Mathieu-Daudé wrote:

Introduce the 'query-accels' QMP command which returns a list
of built-in accelerator names.
 > - Accelerator is a QAPI enum of all existing accelerators,

- AcceleratorInfo is a QAPI structure providing accelerator
   specific information. Currently the common structure base
   provides the name of the accelerator, while the specific
   part is empty, but each accelerator can expand it.

- 'query-accels' QMP command returns a list of @AcceleratorInfo

For example on a KVM-only build we get:

 { "execute": "query-accels" }
 {
 "return": [
 {
 "name": "qtest"
 },
 {
 "name": "kvm"
 }
 ]
 }

Reviewed-by: Eric Blake 
Reviewed-by: Alex Bennée 
Tested-by: Alex Bennée 
Signed-off-by: Philippe Mathieu-Daudé 
---
v8:
- Include code snippet from Markus adding to machine-target.json
   to be able to use enum values or union branches conditional.
- Use accel_find() on enum to be sure the accelerator is enabled
   at runtime (chat with jsnow / eblake).



Hi Phil -- Unfortunately I think I am going to defer on this one until 
Markus is back. I need to chat with him about the right way to design 
this, since I'm also not entirely clear on it myself.


--js


Cc: Eric Blake 
Cc: John Snow 
Cc: Markus Armbruster 





Re: [PATCH v8] qapi: introduce 'query-kvm-cpuid' action

2021-06-02 Thread Philippe Mathieu-Daudé
On 6/2/21 10:46 PM, Eduardo Habkost wrote:
> On Wed, Jun 02, 2021 at 08:17:28PM +0200, Philippe Mathieu-Daudé wrote:
>> Hi Valeriy,
>>
>> (Sorry for not looking earlier than v8)
>>
>> On 5/31/21 2:38 PM, Valeriy Vdovin wrote:
>>> Introducing new qapi method 'query-kvm-cpuid'. This method can be used to
>>> get virtualized cpu model info generated by QEMU during VM initialization in
>>> the form of cpuid representation.
>>>
>>> Diving into more details about virtual cpu generation: QEMU first parses 
>>> '-cpu'
>>> command line option. From there it takes the name of the model as the basis 
>>> for
>>> feature set of the new virtual cpu. After that it uses trailing '-cpu' 
>>> options,
>>> that state if additional cpu features should be present on the virtual cpu 
>>> or
>>> excluded from it (tokens '+'/'-' or '=on'/'=off').
>>> After that QEMU checks if the host's cpu can actually support the derived
>>> feature set and applies host limitations to it.
>>> After this initialization procedure, virtual cpu has it's model and
>>> vendor names, and a working feature set and is ready for identification
>>> instructions such as CPUID.
>>>
>>> Currently full output for this method is only supported for x86 cpus.
>>>
>>> To learn exactly how virtual cpu is presented to the guest machine via CPUID
>>> instruction, new qapi method can be used. By calling 'query-kvm-cpuid'
>>> method, one can get a full listing of all CPUID leafs with subleafs which 
>>> are
>>> supported by the initialized virtual cpu.
>>>
>>> Other than debug, the method is useful in cases when we would like to
>>> utilize QEMU's virtual cpu initialization routines and put the retrieved
>>> values into kernel CPUID overriding mechanics for more precise control
>>> over how various processes perceive its underlying hardware with
>>> container processes as a good example.
>>>
>>> Output format:
>>> The output is a plain list of leaf/subleaf agrument combinations, that
>>> return 4 words in registers EAX, EBX, ECX, EDX.
>>>
>>> Use example:
>>> qmp_request: {
>>>   "execute": "query-kvm-cpuid"
>>> }
>>>
>>> qmp_response: [
>>>   {
>>> "eax": 1073741825,
>>> "edx": 77,
>>> "in_eax": 1073741824,
>>> "ecx": 1447775574,
>>> "ebx": 1263359563,
>>>   },
>>>   {
>>> "eax": 16777339,
>>> "edx": 0,
>>> "in_eax": 1073741825,
>>> "ecx": 0,
>>> "ebx": 0,
>>>   },
>>>   {
>>> "eax": 13,
>>> "edx": 1231384169,
>>> "in_eax": 0,
>>> "ecx": 1818588270,
>>> "ebx": 1970169159,
>>>   },
>>>   {
>>> "eax": 198354,
>>> "edx": 126614527,
>>>   
>>>
>>> Signed-off-by: Valeriy Vdovin 

>>> +##
>>> +# @query-kvm-cpuid:
>>> +#
>>> +# Returns raw data from the KVM CPUID table for the first VCPU.
>>> +# The KVM CPUID table defines the response to the CPUID
>>> +# instruction when executed by the guest operating system.
>>
>> What is specific to KVM here?
>>
>> What about 'query-accel-cpuid' or 'query-vm-cpu-id'?
> 
> The implementation is KVM-specific.  I believe it's a reasonable
> compromise because the implementation is trivial, and a raw copy
> of the KVM CPUID table makes it a more useful (KVM-specific)
> debugging/testing mechanism.
> 
> I don't really mind how the command is called, but I would prefer
> to add a more complex abstraction only if maintainers of other
> accelerators are interested and volunteer to provide similar
> functionality.  I don't want to introduce complexity for use
> cases that may not even exist.

Fine, fair enough.




Re: [PATCH v4 01/15] python: qemu: add timer parameter for qmp.accept socket

2021-06-02 Thread John Snow

On 5/20/21 3:52 AM, Emanuele Giuseppe Esposito wrote:

Alsp add a new _qmp_timer field to the QEMUMachine class.

Let's change the default socket timeout to None, so that if
a subclass needs to add a timer, it can be done by modifying
this private field.

At the same time, restore the timer to be 15 seconds in iotests.py, to
give an upper bound to qemu-iotests execution.

Signed-off-by: Emanuele Giuseppe Esposito 


Hi Emanuele: I'm sorry, but with the recent Python PR this no longer 
applies to origin/master -- the python files got shuffled around a bit 
when I added the new CI tests.


May I please ask you to rebase? You don't have to re-spin just yet, just 
pointing me to the rebase would help me out.


(Also: if you push to gitlab, you can take advantage of the new Python 
CI tests!)


Apologies,
--js




Re: [PATCH qemu] Add basic power management to raspi.

2021-06-02 Thread Philippe Mathieu-Daudé
On 6/2/21 11:33 PM, Nolan wrote:
> On 5/31/21 4:23 AM, Philippe Mathieu-Daudé wrote:
>> Hi Nolan,
>>
>> Thanks for your patch!
>>
>> There is something odd with your email address, which apparently
>> became source...@sigbus.net instead of no...@sigbus.net.
> 
> Ugh, oops. I was trying out sourcehut for this, and reflexively gave
> them a marker email. I'm pretty sure sourcehut won't sell my email
> address, so I'll just change it.
> 
>> On 5/18/21 10:24 PM, ~nolanl wrote:
>>> From: Nolan Leake 
>>>
>>> This is just enough to make reboot and poweroff work.
>>
>> Please precise "for Linux kernels", since this doesn't work
>> with firmwares (ideally we should implement the FIRMWARE_NOTIFY_REBOOT
>> property - which Linux sends - to handle the machine reboot/halt
>> via the videocore firmware model).
> 
> Thanks, good point re: this being tuned to what Linux (and u-boot) do.
> Poking around a bit, it looks like
> "trusted-firmware-a"/"arm-trusted-firmware" uses the same method, as do
> a couple of bare-metal/hobby OSes. Couldn't immediately figure out what
> FreeBSD does.
> 
> I'm not sure I understand your point about FIRMWARE_NOTIFY_REBOOT, my
> understanding is that message is there to tell the GPU firmware that
> we're about to reboot, so it can do things like reload the PCIe USB
> chip's firmware. In my testing without the watchdog module loaded, my
> physical pi4 does not reboot, so it appears that sending
> FIRMWARE_NOTIFY_REBOOT is not enough on its own.

>From the ARM core point of view, once it sent the FIRMWARE_NOTIFY_REBOOT
message, it can't really power-off itself, it waits in a busy loop for
the VC to disable its power domain.

hw/misc/bcm2835_property.c is our model of the VC behavior. IMO this
should be where QEMU shuts down. How I'd model it is:

- ARM: sends FIRMWARE_NOTIFY_REBOOT and loops

- VC emulated via property: delays (200ms?) then calls
  SHUTDOWN_CAUSE_GUEST_RESET.

(it helps to see hw/misc/bcm2835_property.c as an external component).

>>> qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN);
>>> +    } else {
>>> +    qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
>>> +    }
>>> +    }
>>
>> Shouldn't we log the unsupported bits?
> 
> I can add that, I didn't originally because the unsupported writes are
> expected.

I'd prefer we log them, even if unsupported, so in case something
behaves oddly we could look at those bits.

>>> +static void bcm2835_powermgt_reset(DeviceState *dev)
>>> +{
>>> +    BCM2835PowerMgtState *s = BCM2835_POWERMGT(dev);
>>> +
>>> +    s->rstc = 0x0102;
>>> +    s->rsts = 0x1000;
>>> +    s->wdog = 0x;
>>
>> Where these bits come from?
> 
> From my pi4. https://elinux.org/BCM2835_registers agrees (processed from
> Broadcom source code).

OK, so please add a comment referring to
https://elinux.org/BCM2835_registers#PM.

Looking forward for v2 :)

Phil.



[PATCH qemu v2] Add basic power management to raspi.

2021-06-02 Thread ~nolanl
From: Nolan Leake 

This is just enough to make reboot and poweroff work. Works for
linux, u-boot, and the arm trusted firmware. Not tested, but should
work for plan9, and bare-metal/hobby OSes, since they seem to generally
do what linux does for reset.

The watchdog timer functionality is not yet implemented.

Resolves: https://gitlab.com/qemu-project/qemu/-/issues/64
Signed-off-by: Nolan Leake 
---
 hw/arm/bcm2835_peripherals.c |  13 ++-
 hw/misc/bcm2835_powermgt.c   | 159 +++
 hw/misc/meson.build  |   1 +
 include/hw/arm/bcm2835_peripherals.h |   3 +-
 include/hw/misc/bcm2835_powermgt.h   |  29 +
 5 files changed, 203 insertions(+), 2 deletions(-)
 create mode 100644 hw/misc/bcm2835_powermgt.c
 create mode 100644 include/hw/misc/bcm2835_powermgt.h

diff --git a/hw/arm/bcm2835_peripherals.c b/hw/arm/bcm2835_peripherals.c
index dcff13433e..48538c9360 100644
--- a/hw/arm/bcm2835_peripherals.c
+++ b/hw/arm/bcm2835_peripherals.c
@@ -126,6 +126,10 @@ static void bcm2835_peripherals_init(Object *obj)
 
 object_property_add_const_link(OBJECT(>dwc2), "dma-mr",
OBJECT(>gpu_bus_mr));
+
+/* Power Management */
+object_initialize_child(obj, "powermgt", >powermgt,
+TYPE_BCM2835_POWERMGT);
 }
 
 static void bcm2835_peripherals_realize(DeviceState *dev, Error **errp)
@@ -364,9 +368,16 @@ static void bcm2835_peripherals_realize(DeviceState *dev, 
Error **errp)
 qdev_get_gpio_in_named(DEVICE(>ic), BCM2835_IC_GPU_IRQ,
INTERRUPT_USB));
 
+/* Power Management */
+if (!sysbus_realize(SYS_BUS_DEVICE(>powermgt), errp)) {
+return;
+}
+
+memory_region_add_subregion(>peri_mr, PM_OFFSET,
+sysbus_mmio_get_region(SYS_BUS_DEVICE(>powermgt), 0));
+
 create_unimp(s, >txp, "bcm2835-txp", TXP_OFFSET, 0x1000);
 create_unimp(s, >armtmr, "bcm2835-sp804", ARMCTRL_TIMER0_1_OFFSET, 
0x40);
-create_unimp(s, >powermgt, "bcm2835-powermgt", PM_OFFSET, 0x114);
 create_unimp(s, >i2s, "bcm2835-i2s", I2S_OFFSET, 0x100);
 create_unimp(s, >smi, "bcm2835-smi", SMI_OFFSET, 0x100);
 create_unimp(s, >spi[0], "bcm2835-spi0", SPI0_OFFSET, 0x20);
diff --git a/hw/misc/bcm2835_powermgt.c b/hw/misc/bcm2835_powermgt.c
new file mode 100644
index 00..55455bbd60
--- /dev/null
+++ b/hw/misc/bcm2835_powermgt.c
@@ -0,0 +1,159 @@
+/*
+ * BCM2835 Power Management emulation
+ *
+ * Copyright (C) 2017 Marcin Chojnacki 
+ * Copyright (C) 2021 Nolan Leake 
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/log.h"
+#include "qemu/module.h"
+#include "hw/misc/bcm2835_powermgt.h"
+#include "migration/vmstate.h"
+#include "sysemu/runstate.h"
+
+#define PASSWORD 0x5a00
+#define PASSWORD_MASK 0xff00
+
+#define R_RSTC 0x1c
+#define V_RSTC_RESET 0x20
+#define R_RSTS 0x20
+#define V_RSTS_POWEROFF 0x555 /* Linux uses partition 63 to indicate halt. */
+#define R_WDOG 0x24
+
+static uint64_t bcm2835_powermgt_read(void *opaque, hwaddr offset,
+  unsigned size)
+{
+BCM2835PowerMgtState *s = (BCM2835PowerMgtState *)opaque;
+uint32_t res = 0;
+
+switch (offset) {
+case R_RSTC:
+res = s->rstc;
+break;
+case R_RSTS:
+res = s->rsts;
+break;
+case R_WDOG:
+res = s->wdog;
+break;
+
+default:
+qemu_log_mask(LOG_UNIMP,
+  "bcm2835_powermgt_read: Unknown offset 0x%08"HWADDR_PRIx
+  "\n", offset);
+res = 0;
+break;
+}
+
+return res;
+}
+
+static void bcm2835_powermgt_write(void *opaque, hwaddr offset,
+   uint64_t value, unsigned size)
+{
+BCM2835PowerMgtState *s = (BCM2835PowerMgtState *)opaque;
+
+if ((value & PASSWORD_MASK) != PASSWORD) {
+qemu_log_mask(LOG_GUEST_ERROR,
+  "bcm2835_powermgt_write: Bad password 0x%"PRIx64
+  " at offset 0x%08"HWADDR_PRIx"\n",
+  value, offset);
+return;
+}
+
+value = value & ~PASSWORD_MASK;
+
+switch (offset) {
+case R_RSTC:
+s->rstc = value;
+if (value & V_RSTC_RESET) {
+if ((s->rsts & 0xfff) == V_RSTS_POWEROFF) {
+qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN);
+} else {
+qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
+}
+}
+break;
+case R_RSTS:
+qemu_log_mask(LOG_UNIMP,
+  "bcm2835_powermgt_write: RSTS\n");
+s->rsts = value;
+break;
+case R_WDOG:
+qemu_log_mask(LOG_UNIMP,
+  "bcm2835_powermgt_write: WDOG\n");
+s->wdog = value;
+break;
+
+default:
+   

Re: [PATCH v2 04/28] softfloat: Move minmax_flags to softfloat-parts.c.inc

2021-06-02 Thread Richard Henderson

On 5/25/21 8:06 AM, Richard Henderson wrote:

+which = parts_minmax(, , s, flags, _params);
+if (unlikely(which < 0)) {
+/* Some sort of nan, need to repack default and silenced nans. */
+return float32_round_pack_canonical(, s);
+}
+return which ? b : a;


I've just realized that if flush_inputs_to_zero is on, then the result should 
reflect that rather than returning the denormal.


Will fix.


r~



Re: [PATCH v2 04/28] softfloat: Move minmax_flags to softfloat-parts.c.inc

2021-06-02 Thread Richard Henderson

On 6/2/21 1:36 PM, Alex Bennée wrote:


Richard Henderson  writes:


Rename to parts$N_minmax.  Combine 3 bool arguments to a bitmask,
return a tri-state value to indicate nan vs unchanged operand.
Introduce ftype_minmax functions as a common optimization point.
Fold bfloat16 expansions into the same macro as the other types.

Signed-off-by: Richard Henderson 
---



-switch (a.cls) {
-case float_class_normal:
-a_exp = a.exp;
-break;
-case float_class_inf:
-a_exp = INT_MAX;
-break;
-case float_class_zero:
-a_exp = INT_MIN;
-break;
-default:
-g_assert_not_reached();
-break;
-}
-switch (b.cls) {
-case float_class_normal:
-b_exp = b.exp;
-break;
-case float_class_inf:
-b_exp = INT_MAX;
-break;
-case float_class_zero:
-b_exp = INT_MIN;
-break;
-default:
-g_assert_not_reached();
-break;
-}
-



+if (unlikely(ab_mask != float_cmask_normal)) {
+switch (a->cls) {
+case float_class_normal:
+break;
+case float_class_inf:
+a_exp = INT16_MAX;


We've gone from min/max of our internal representation to INT16_MIN/MAX
- I guess that doesn't break until we get to Float256 but why the change?


Ah, because I've changed from "bool a_less" to "int cmp".  I subtract the two 
exponents and I don't want that subtraction to overflow.



r~



Re: [RFC PATCH] target/ppc: fix address translation bug for hash table mmus

2021-06-02 Thread Richard Henderson

On 6/2/21 12:58 PM, Bruno Piazera Larsen wrote:
For the use from ppc_cpu_get_phys_page_debug, you'd pass in 
cpu_mmu_index(env, false).


ppc_cpu_get_phys_page_debug has 2 calls to ppc_xlate, one using the data MMU, 
the other using the instruction MMU. I'm guessing I should pass both, right?


Yes.

But here we have another bit that confuses me: cpu_mmu_index returns 0 if in 
user mode, or uses the information stored in env to get it, so I don't see how 
that would be different from getting directly. Unless the point is to have 
ppc_*_xlate be generic and pc_*_debug knows the info in env is correct. Is that it?


The issue is that

(1) ppc_*_xlate should perform the lookup requested, and mmu_idx
does not *necessarily* correspond to the current contents of
env->msr et al.  See (2).

(2) There is a secondary call to ppc_radix64_partition_scoped_xlate
for which the second stage page table should be read
with hypervisor permissions, and not the permissions of the
original memory access.

Note that ppc_radix64_check_prot checks msr_pr directly.

Thus the second stage lookup should use mmu_idx = 5
(HV kernel virtual mode).  If I understand things correctly...







+    const short HV = 1, IR = 2, DR = 3;
+    bool MSR[3];
+    MSR[HV] = dmmu_idx & 2,
+    MSR[IR] = immu_idx & 4,
+    MSR[DR] = dmmu_idx & 4;


There's no point in the array.  Just use three different scalars (real_mode, 
hv, and pr (note that pr is the major portion of the bug as reported)). 
Additionally, you'll not be distinguishing immu_idx and dmmu_idx, but using 
the single idx that's given.


Ah, yeah, that's the "more complex than necessary, but it was easy for me to 
read" part. Scalars are a good solution. In this function in specific, PR 
doesn't actually show up anywhere, so I would actually only need 2. Anyway, 
will start working on this.


Oh, I'll note that your constants above are wrong.  I think that you should 
have some common routines in (mmu-)internal.h:


/*
 * These correspond to the mmu_idx values computed in
 * hreg_compute_hflags_value.  See the tables therein.
 */
static inline bool mmuidx_pr(int idx) { return idx & 1; }
static inline bool mmuidx_real(int idx) { return idx & 2; }
static inline bool mmuidx_hv(int idx) { return idx & 4; }

because you'll want to use these past mmu-radix64.c.

Then you also have a single place to adjust if the mmu_idx are reordered at a 
later date.



r~



Re: [PATCH qemu] Add basic power management to raspi.

2021-06-02 Thread Nolan

On 5/31/21 4:23 AM, Philippe Mathieu-Daudé wrote:

Hi Nolan,

Thanks for your patch!

There is something odd with your email address, which apparently
became source...@sigbus.net instead of no...@sigbus.net.


Ugh, oops. I was trying out sourcehut for this, and reflexively gave 
them a marker email. I'm pretty sure sourcehut won't sell my email 
address, so I'll just change it.



On 5/18/21 10:24 PM, ~nolanl wrote:

From: Nolan Leake 

This is just enough to make reboot and poweroff work.


Please precise "for Linux kernels", since this doesn't work
with firmwares (ideally we should implement the FIRMWARE_NOTIFY_REBOOT
property - which Linux sends - to handle the machine reboot/halt
via the videocore firmware model).


Thanks, good point re: this being tuned to what Linux (and u-boot) do. 
Poking around a bit, it looks like 
"trusted-firmware-a"/"arm-trusted-firmware" uses the same method, as do 
a couple of bare-metal/hobby OSes. Couldn't immediately figure out what 
FreeBSD does.


I'm not sure I understand your point about FIRMWARE_NOTIFY_REBOOT, my 
understanding is that message is there to tell the GPU firmware that 
we're about to reboot, so it can do things like reload the PCIe USB 
chip's firmware. In my testing without the watchdog module loaded, my 
physical pi4 does not reboot, so it appears that sending 
FIRMWARE_NOTIFY_REBOOT is not enough on its own.



Notably, the
watchdog timer functionality is not yet implemented.

Resolves: https://gitlab.com/qemu-project/qemu/-/issues/64
Signed-off-by: Nolan Leake 
---
  hw/arm/bcm2835_peripherals.c |  13 ++-
  hw/misc/bcm2835_powermgt.c   | 157 +++
  hw/misc/meson.build  |   1 +
  include/hw/arm/bcm2835_peripherals.h |   3 +-
  include/hw/misc/bcm2835_powermgt.h   |  29 +
  5 files changed, 201 insertions(+), 2 deletions(-)
  create mode 100644 hw/misc/bcm2835_powermgt.c
  create mode 100644 include/hw/misc/bcm2835_powermgt.h

diff --git a/hw/arm/bcm2835_peripherals.c b/hw/arm/bcm2835_peripherals.c
index dcff13433e..48538c9360 100644
--- a/hw/arm/bcm2835_peripherals.c
+++ b/hw/arm/bcm2835_peripherals.c
@@ -126,6 +126,10 @@ static void bcm2835_peripherals_init(Object *obj)
  
  object_property_add_const_link(OBJECT(>dwc2), "dma-mr",

 OBJECT(>gpu_bus_mr));
+
+/* Power Management */
+object_initialize_child(obj, "powermgt", >powermgt,
+TYPE_BCM2835_POWERMGT);
  }
  
  static void bcm2835_peripherals_realize(DeviceState *dev, Error **errp)

@@ -364,9 +368,16 @@ static void bcm2835_peripherals_realize(DeviceState *dev, 
Error **errp)
  qdev_get_gpio_in_named(DEVICE(>ic), BCM2835_IC_GPU_IRQ,
 INTERRUPT_USB));
  
+/* Power Management */

+if (!sysbus_realize(SYS_BUS_DEVICE(>powermgt), errp)) {
+return;
+}
+
+memory_region_add_subregion(>peri_mr, PM_OFFSET,
+sysbus_mmio_get_region(SYS_BUS_DEVICE(>powermgt), 0));
+
  create_unimp(s, >txp, "bcm2835-txp", TXP_OFFSET, 0x1000);
  create_unimp(s, >armtmr, "bcm2835-sp804", ARMCTRL_TIMER0_1_OFFSET, 
0x40);
-create_unimp(s, >powermgt, "bcm2835-powermgt", PM_OFFSET, 0x114);
  create_unimp(s, >i2s, "bcm2835-i2s", I2S_OFFSET, 0x100);
  create_unimp(s, >smi, "bcm2835-smi", SMI_OFFSET, 0x100);
  create_unimp(s, >spi[0], "bcm2835-spi0", SPI0_OFFSET, 0x20);
diff --git a/hw/misc/bcm2835_powermgt.c b/hw/misc/bcm2835_powermgt.c
new file mode 100644
index 00..81107ecc8f
--- /dev/null
+++ b/hw/misc/bcm2835_powermgt.c
@@ -0,0 +1,157 @@
+/*
+ * BCM2835 Power Management emulation
+ *
+ * Copyright (C) 2017 Marcin Chojnacki 
+ * Copyright (C) 2021 Nolan Leake 
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/log.h"
+#include "qemu/module.h"
+#include "hw/misc/bcm2835_powermgt.h"
+#include "migration/vmstate.h"
+#include "sysemu/runstate.h"
+
+#define PASSWORD 0x5a00
+#define PASSWORD_MASK 0xff00
+
+#define R_RSTC 0x1c
+#define V_RSTC_RESET 0x20
+#define R_RSTS 0x20
+#define V_RSTS_POWEROFF 0x555
+#define R_WDOG 0x24
+
+static uint64_t bcm2835_powermgt_read(void *opaque, hwaddr offset,
+  unsigned size)
+{
+BCM2835PowerMgtState *s = (BCM2835PowerMgtState *)opaque;
+uint32_t res = 0;
+
+assert(size == 4);


Instead of this assert, add in bcm2835_powermgt_ops:

   .impl.min_access_size = 4,
   .impl.max_access_size = 4,


Will do.


+
+switch (offset) {
+case R_RSTC:
+res = s->rstc;
+break;
+case R_RSTS:
+res = s->rsts;
+break;
+case R_WDOG:
+res = s->wdog;
+break;
+
+default:
+qemu_log_mask(LOG_UNIMP,
+  "bcm2835_powermgt_read: Unknown offset %x\n",
+  (int)offset);
+res = 0;
+ 

Re: [PATCH v2 10/10] nbd: move connection code from block/nbd to nbd/client-connection

2021-06-02 Thread Eric Blake
On Thu, Apr 08, 2021 at 05:08:27PM +0300, Vladimir Sementsov-Ogievskiy wrote:
> We now have bs-independent connection API, which consists of four
> functions:
> 
>   nbd_client_connection_new()
>   nbd_client_connection_unref()
>   nbd_co_establish_connection()
>   nbd_co_establish_connection_cancel()
> 
> Move them to a separate file together with NBDClientConnection
> structure which becomes private to the new API.
> 
> Signed-off-by: Vladimir Sementsov-Ogievskiy 
> ---
> 
> Hmm. I keep only Virtuozzo's copyright in a new file, as actually I've
> developed nbd-reconnection code. Still probably safer to save all
> copyrights. Let me now if you think so and I'll add them.

I trust git's version log better than what the file header itself
states.  But in this particular case (the new file has only functions
that you demonstrably contributed), I think you are okay in listing
only your own copyright, instead of carrying along everything else
from the file you split out of.  If anyone objects, we can always add
the details back in.  However, it may be good to include a disclaimer
in your commit message proper mentioning your choice in copyright on
the new file.


-- 
Eric Blake, Principal Software Engineer
Red Hat, Inc.   +1-919-301-3266
Virtualization:  qemu.org | libvirt.org




Re: [PATCH v3 13/33] block/nbd: introduce nbd_client_connection_release()

2021-06-02 Thread Eric Blake
On Fri, Apr 16, 2021 at 11:08:51AM +0300, Vladimir Sementsov-Ogievskiy wrote:
> Signed-off-by: Vladimir Sementsov-Ogievskiy 
> ---
>  block/nbd.c | 43 ++-
>  1 file changed, 26 insertions(+), 17 deletions(-)

Commit message said what, but not why.  Presumably this is one more
bit of refactoring to make the upcoming file split in a later patch
easier.  But patch 12/33 said it was the last step before a new file,
and this patch isn't yet at a new file.  Missing some continuity in
your commit messages?

> 
> diff --git a/block/nbd.c b/block/nbd.c
> index 21a4039359..8531d019b2 100644
> --- a/block/nbd.c
> +++ b/block/nbd.c
> @@ -118,7 +118,7 @@ typedef struct BDRVNBDState {
>  NBDClientConnection *conn;
>  } BDRVNBDState;
>  
> -static void nbd_free_connect_thread(NBDClientConnection *conn);
> +static void nbd_client_connection_release(NBDClientConnection *conn);

Is it necessary for a forward declaration, or can you just implement
the new function prior to its users?

At any rate, the refactoring looks sane.

-- 
Eric Blake, Principal Software Engineer
Red Hat, Inc.   +1-919-301-3266
Virtualization:  qemu.org | libvirt.org




Re: [PATCH v3 12/33] block/nbd: introduce nbd_client_connection_new()

2021-06-02 Thread Eric Blake
On Fri, Apr 16, 2021 at 11:08:50AM +0300, Vladimir Sementsov-Ogievskiy wrote:
> This is the last step of creating bs-independent nbd connection
> interface. With next commit we can finally move it to separate file.
> 
> Signed-off-by: Vladimir Sementsov-Ogievskiy 
> Reviewed-by: Roman Kagan 
> ---
>  block/nbd.c | 15 +--
>  1 file changed, 9 insertions(+), 6 deletions(-)
>

Reviewed-by: Eric Blake 

-- 
Eric Blake, Principal Software Engineer
Red Hat, Inc.   +1-919-301-3266
Virtualization:  qemu.org | libvirt.org




Re: [PATCH v3 11/33] block/nbd: rename NBDConnectThread to NBDClientConnection

2021-06-02 Thread Eric Blake
On Fri, Apr 16, 2021 at 11:08:49AM +0300, Vladimir Sementsov-Ogievskiy wrote:
> We are going to move connection code to own file and want clear names
> and APIs.

We are going to move the connection code to its own file, and want
clear names and APIs first.

> 
> The structure is shared between user and (possibly) several runs of
> connect-thread. So it's wrong to call it "thread". Let's rename to
> something more generic.
> 
> Appropriately rename connect_thread and thr variables to conn.
> 
> Signed-off-by: Vladimir Sementsov-Ogievskiy 
> ---
>  block/nbd.c | 137 ++--
>  1 file changed, 68 insertions(+), 69 deletions(-)
> 

Reviewed-by: Eric Blake 

-- 
Eric Blake, Principal Software Engineer
Red Hat, Inc.   +1-919-301-3266
Virtualization:  qemu.org | libvirt.org




Re: [PATCH v3 10/33] block/nbd: make nbd_co_establish_connection_cancel() bs-independent

2021-06-02 Thread Eric Blake
On Fri, Apr 16, 2021 at 11:08:48AM +0300, Vladimir Sementsov-Ogievskiy wrote:
> nbd_co_establish_connection_cancel() actually needs only pointer to
> NBDConnectThread. So, make it clean.
> 
> Signed-off-by: Vladimir Sementsov-Ogievskiy 
> Reviewed-by: Roman Kagan 
> ---
>  block/nbd.c | 16 +++-
>  1 file changed, 7 insertions(+), 9 deletions(-)
> 
> diff --git a/block/nbd.c b/block/nbd.c
> index dd97ea0916..dab73bdf3b 100644
> --- a/block/nbd.c
> +++ b/block/nbd.c

>  /*
>   * nbd_co_establish_connection_cancel
> - * Cancel nbd_co_establish_connection asynchronously: it will finish soon, to
> - * allow drained section to begin.
> + * Cancel nbd_co_establish_connection() asynchronously. Note, that it doesn't
> + * stop the thread itself neither close the socket. It just safely wakes
> + * nbd_co_establish_connection() sleeping in the yield().

Grammar suggestion:

Note that this function neither directly stops the thread nor closes
the socket, but rather safely wakes nbd_co_establish_connection()
which is sleeping in yield(), triggering subsequent cleanup there.

Reviewed-by: Eric Blake 

-- 
Eric Blake, Principal Software Engineer
Red Hat, Inc.   +1-919-301-3266
Virtualization:  qemu.org | libvirt.org




Re: [PATCH v8] qapi: introduce 'query-kvm-cpuid' action

2021-06-02 Thread Eduardo Habkost
On Wed, Jun 02, 2021 at 03:51:02PM -0500, Eric Blake wrote:
> On Mon, May 31, 2021 at 03:38:06PM +0300, Valeriy Vdovin wrote:
[...]
> > +##
> > +# @CpuidEntry:
> > +#
> > +# A single entry of a CPUID response.
> > +#
> > +# One entry holds full set of information (leaf) returned to the guest in 
> > response
> > +# to it calling a CPUID instruction with eax, ecx used as the agruments to 
> > that
> 
> arguments
> 
> > +# instruction. ecx is an optional argument as not all of the leaves 
> > support it.
> 
> Is there a default value of ecx for when it is not provided by the
> user but needed by the leaf?  Or is it an error if ecx is omitted in
> that case?  Similarly, is it an error if ecx is provided but not
> needed?

What does "not provided by the user" mean here?  This is not
describing the input to a QMP command, but the input to the CPUID
instruction.

-- 
Eduardo




Re: [RFC PATCH 1/4] target/ppc: Don't compile ppc_tlb_invalid_all without TCG

2021-06-02 Thread Fabiano Rosas
"Lucas Mateus Castro (alqotel)"  writes:

> The function ppc_tlb_invalid_all is not compiled anymore in a TCG-less
> environment, and the call to that function has been disabled in this
> situation.
>
> Signed-off-by: Lucas Mateus Castro (alqotel) 
> ---
> Is there a better way than to deal with the
> ppc_tlb_invalidate_all call than ifdef? I couldn't think of one.
> ---
>  target/ppc/cpu_init.c   | 4 
>  target/ppc/mmu_helper.c | 4 
>  2 files changed, 8 insertions(+)
>
> diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c
> index 74a397ad6c..2051f24467 100644
> --- a/target/ppc/cpu_init.c
> +++ b/target/ppc/cpu_init.c
> @@ -9114,7 +9114,11 @@ static void ppc_cpu_reset(DeviceState *dev)
>  #if !defined(CONFIG_USER_ONLY)
>  env->nip = env->hreset_vector | env->excp_prefix;
>  if (env->mmu_model != POWERPC_MMU_REAL) {
> +#if defined(CONFIG_TCG)
>  ppc_tlb_invalidate_all(env);
> +#else
> + cpu_abort(env_cpu(env),"PowerPC not in real mode, invalid in this 
> build\n");

This looks like it would always abort when !TCG with most processors
since their mmu_model would be different from POWERPC_MMU_REAL. Leaving
the whole if statement out would be better and there's no need for an
error.

> +#endif
>  }
>  #endif
>  
> diff --git a/target/ppc/mmu_helper.c b/target/ppc/mmu_helper.c
> index 1ecb36e85a..803b66f2b0 100644
> --- a/target/ppc/mmu_helper.c
> +++ b/target/ppc/mmu_helper.c
> @@ -825,6 +825,7 @@ static int mmubooke_get_physical_address(CPUPPCState 
> *env, mmu_ctx_t *ctx,
>  return ret;
>  }
>  
> +#ifdef CONFIG_TCG
>  static void booke206_flush_tlb(CPUPPCState *env, int flags,
> const int check_iprot)
>  {
> @@ -846,6 +847,7 @@ static void booke206_flush_tlb(CPUPPCState *env, int 
> flags,
>  
>  tlb_flush(env_cpu(env));
>  }
> +#endif
>  
>  static hwaddr booke206_tlb_to_page_size(CPUPPCState *env,
>  ppcmas_tlb_t *tlb)
> @@ -1952,6 +1954,7 @@ void helper_store_601_batl(CPUPPCState *env, uint32_t 
> nr, target_ulong value)
>  }
>  #endif
>  
> +#ifdef CONFIG_TCG
>  
> /*/
>  /* TLB management */
>  void ppc_tlb_invalidate_all(CPUPPCState *env)
> @@ -1995,6 +1998,7 @@ void ppc_tlb_invalidate_all(CPUPPCState *env)
>  break;
>  }
>  }
> +#endif
>  
>  #ifdef CONFIG_TCG
>  void ppc_tlb_invalidate_one(CPUPPCState *env, target_ulong addr)



Re: [PATCH v8] qapi: introduce 'query-kvm-cpuid' action

2021-06-02 Thread Eric Blake
On Mon, May 31, 2021 at 03:38:06PM +0300, Valeriy Vdovin wrote:
> Introducing new qapi method 'query-kvm-cpuid'. This method can be used to
> get virtualized cpu model info generated by QEMU during VM initialization in
> the form of cpuid representation.
> 
> 
> Use example:
> qmp_request: {
>   "execute": "query-kvm-cpuid"
> }
> 
> qmp_response: [
>   {
> "eax": 1073741825,
> "edx": 77,
> "in_eax": 1073741824,
> "ecx": 1447775574,
> "ebx": 1263359563,
>   },

JSON does not permit a trailing ',' before '}'; which means you did
not actually paste an actual QMP response here.

> ---
>  qapi/machine-target.json   | 43 ++
>  target/i386/kvm/kvm.c  | 37 
>  tests/qtest/qmp-cmd-test.c |  1 +
>  3 files changed, 81 insertions(+)
> 
> diff --git a/qapi/machine-target.json b/qapi/machine-target.json
> index e7811654b7..a83180dd24 100644
> --- a/qapi/machine-target.json
> +++ b/qapi/machine-target.json
> @@ -329,3 +329,46 @@
>  ##
>  { 'command': 'query-cpu-definitions', 'returns': ['CpuDefinitionInfo'],
>'if': 'defined(TARGET_PPC) || defined(TARGET_ARM) || defined(TARGET_I386) 
> || defined(TARGET_S390X) || defined(TARGET_MIPS)' }
> +
> +##
> +# @CpuidEntry:
> +#
> +# A single entry of a CPUID response.
> +#
> +# One entry holds full set of information (leaf) returned to the guest in 
> response
> +# to it calling a CPUID instruction with eax, ecx used as the agruments to 
> that

arguments

> +# instruction. ecx is an optional argument as not all of the leaves support 
> it.

Is there a default value of ecx for when it is not provided by the
user but needed by the leaf?  Or is it an error if ecx is omitted in
that case?  Similarly, is it an error if ecx is provided but not
needed?

> +#
> +# @in_eax: CPUID argument in eax
> +# @in_ecx: CPUID argument in ecx

Should be in-eax, in-ecx.

> +# @eax: eax
> +# @ebx: ebx
> +# @ecx: ecx
> +# @edx: edx
> +#
> +# Since: 6.1
> +##
> +{ 'struct': 'CpuidEntry',
> +  'data': { 'in_eax' : 'uint32',
> +'*in_ecx' : 'uint32',
> +'eax' : 'uint32',
> +'ebx' : 'uint32',
> +'ecx' : 'uint32',
> +'edx' : 'uint32'
> +  },
> +  'if': 'defined(TARGET_I386) && defined(CONFIG_KVM)' }
> +
> +##
> +# @query-kvm-cpuid:
> +#
> +# Returns raw data from the KVM CPUID table for the first VCPU.
> +# The KVM CPUID table defines the response to the CPUID
> +# instruction when executed by the guest operating system.
> +#
> +# Returns: a list of CpuidEntry
> +#
> +# Since: 6.1
> +##
> +{ 'command': 'query-kvm-cpuid',
> +  'returns': ['CpuidEntry'],
> +  'if': 'defined(TARGET_I386) && defined(CONFIG_KVM)' }

-- 
Eric Blake, Principal Software Engineer
Red Hat, Inc.   +1-919-301-3266
Virtualization:  qemu.org | libvirt.org




Re: [PATCH] target/i386/sev: Ensure sev_fw_errlist is sync with update-linux-headers

2021-06-02 Thread Eduardo Habkost
On Wed, Jun 02, 2021 at 12:48:18PM +0200, Philippe Mathieu-Daudé wrote:
> This patch was supposed to go via Eduardo's tree but he
> missed it, can it go via qemu-trivial instead?

My apologies, again.  I'm still behind on my qemu-devel backlog,
and this was still buried in my inbox.

> 
> On 2/19/21 7:01 PM, Philippe Mathieu-Daudé wrote:
> > Ensure sev_fw_errlist[] is updated after running
> > the update-linux-headers.sh script.
> > 
> > Signed-off-by: Philippe Mathieu-Daudé 
> > ---
> > Based-on: <20210218151633.215374-1-cku...@redhat.com>
> > ---
> >  target/i386/sev.c | 5 -
> >  1 file changed, 4 insertions(+), 1 deletion(-)
> > 
> > diff --git a/target/i386/sev.c b/target/i386/sev.c
> > index 37690ae809c..92c69a23769 100644
> > --- a/target/i386/sev.c
> > +++ b/target/i386/sev.c
> > @@ -87,7 +87,7 @@ typedef struct __attribute__((__packed__)) SevInfoBlock {
> >  static SevGuestState *sev_guest;
> >  static Error *sev_mig_blocker;
> >  
> > -static const char *const sev_fw_errlist[] = {
> > +static const char *const sev_fw_errlist[SEV_RET_MAX] = {
> >  [SEV_RET_SUCCESS]= "",
> >  [SEV_RET_INVALID_PLATFORM_STATE] = "Platform state is invalid",
> >  [SEV_RET_INVALID_GUEST_STATE]= "Guest state is invalid",
> > @@ -114,6 +114,8 @@ static const char *const sev_fw_errlist[] = {
> >  [SEV_RET_RESOURCE_LIMIT] = "Required firmware resource 
> > depleted",
> >  [SEV_RET_SECURE_DATA_INVALID]= "Part-specific integrity check 
> > failure",
> >  };
> > +/* Ensure sev_fw_errlist[] is updated after running 
> > update-linux-headers.sh */
> > +QEMU_BUILD_BUG_ON(SEV_RET_SECURE_DATA_INVALID + 1 != SEV_RET_MAX);

A mechanism to notify us when sev_fw_errlist needs to be updated
would be useful, but I'm not sure I agree with this change.
I expect update-linux-headers patches always consist of 100%
automated changes.  This patch would require a manual update of
target/i386/sev.c to be included in the same commit as
the header update.


> >  
> >  #define SEV_FW_MAX_ERROR  ARRAY_SIZE(sev_fw_errlist)
> >  
> > @@ -160,6 +162,7 @@ fw_error_to_str(int code)
> >  if (code < 0 || code >= SEV_FW_MAX_ERROR) {
> >  return "unknown error";
> >  }
> > +assert(sev_fw_errlist[code]);
> >  
> >  return sev_fw_errlist[code];
> >  }
> > 
> 

-- 
Eduardo




Re: [PATCH v8] qapi: introduce 'query-kvm-cpuid' action

2021-06-02 Thread Eduardo Habkost
On Wed, Jun 02, 2021 at 08:17:28PM +0200, Philippe Mathieu-Daudé wrote:
> Hi Valeriy,
> 
> (Sorry for not looking earlier than v8)
> 
> On 5/31/21 2:38 PM, Valeriy Vdovin wrote:
> > Introducing new qapi method 'query-kvm-cpuid'. This method can be used to
> > get virtualized cpu model info generated by QEMU during VM initialization in
> > the form of cpuid representation.
> > 
> > Diving into more details about virtual cpu generation: QEMU first parses 
> > '-cpu'
> > command line option. From there it takes the name of the model as the basis 
> > for
> > feature set of the new virtual cpu. After that it uses trailing '-cpu' 
> > options,
> > that state if additional cpu features should be present on the virtual cpu 
> > or
> > excluded from it (tokens '+'/'-' or '=on'/'=off').
> > After that QEMU checks if the host's cpu can actually support the derived
> > feature set and applies host limitations to it.
> > After this initialization procedure, virtual cpu has it's model and
> > vendor names, and a working feature set and is ready for identification
> > instructions such as CPUID.
> > 
> > Currently full output for this method is only supported for x86 cpus.
> > 
> > To learn exactly how virtual cpu is presented to the guest machine via CPUID
> > instruction, new qapi method can be used. By calling 'query-kvm-cpuid'
> > method, one can get a full listing of all CPUID leafs with subleafs which 
> > are
> > supported by the initialized virtual cpu.
> > 
> > Other than debug, the method is useful in cases when we would like to
> > utilize QEMU's virtual cpu initialization routines and put the retrieved
> > values into kernel CPUID overriding mechanics for more precise control
> > over how various processes perceive its underlying hardware with
> > container processes as a good example.
> > 
> > Output format:
> > The output is a plain list of leaf/subleaf agrument combinations, that
> > return 4 words in registers EAX, EBX, ECX, EDX.
> > 
> > Use example:
> > qmp_request: {
> >   "execute": "query-kvm-cpuid"
> > }
> > 
> > qmp_response: [
> >   {
> > "eax": 1073741825,
> > "edx": 77,
> > "in_eax": 1073741824,
> > "ecx": 1447775574,
> > "ebx": 1263359563,
> >   },
> >   {
> > "eax": 16777339,
> > "edx": 0,
> > "in_eax": 1073741825,
> > "ecx": 0,
> > "ebx": 0,
> >   },
> >   {
> > "eax": 13,
> > "edx": 1231384169,
> > "in_eax": 0,
> > "ecx": 1818588270,
> > "ebx": 1970169159,
> >   },
> >   {
> > "eax": 198354,
> > "edx": 126614527,
> >   
> > 
> > Signed-off-by: Valeriy Vdovin 
> 
> ---
> 
> > 
> > v2: - Removed leaf/subleaf iterators.
> > - Modified cpu_x86_cpuid to return false in cases when count is
> >   greater than supported subleaves.
> > v3: - Fixed structure name coding style.
> > - Added more comments
> > - Ensured buildability for non-x86 targets.
> > v4: - Fixed cpu_x86_cpuid return value logic and handling of 0xA leaf.
> > - Fixed comments.
> > - Removed target check in qmp_query_cpu_model_cpuid.
> > v5: - Added error handling code in qmp_query_cpu_model_cpuid
> > v6: - Fixed error handling code. Added method to query_error_class
> > v7: - Changed implementation in favor of cached cpuid_data for
> >   KVM_SET_CPUID2
> > v8: - Renamed qmp method to query-kvm-cpuid and some fields in response.
> > - Modified documentation to qmp method
> > - Removed helper struct declaration
> > ---
> 
> ^ Below this '---' go your comments.
> 
> >  qapi/machine-target.json   | 43 ++
> >  target/i386/kvm/kvm.c  | 37 
> >  tests/qtest/qmp-cmd-test.c |  1 +
> >  3 files changed, 81 insertions(+)
> > 
> > diff --git a/qapi/machine-target.json b/qapi/machine-target.json
> > index e7811654b7..a83180dd24 100644
> > --- a/qapi/machine-target.json
> > +++ b/qapi/machine-target.json
> > @@ -329,3 +329,46 @@
> >  ##
> >  { 'command': 'query-cpu-definitions', 'returns': ['CpuDefinitionInfo'],
> >'if': 'defined(TARGET_PPC) || defined(TARGET_ARM) || 
> > defined(TARGET_I386) || defined(TARGET_S390X) || defined(TARGET_MIPS)' }
> > +
> > +##
> > +# @CpuidEntry:
> > +#
> > +# A single entry of a CPUID response.
> > +#
> > +# One entry holds full set of information (leaf) returned to the guest in 
> > response
> > +# to it calling a CPUID instruction with eax, ecx used as the agruments to 
> > that
> > +# instruction. ecx is an optional argument as not all of the leaves 
> > support it.
> > +#
> > +# @in_eax: CPUID argument in eax
> > +# @in_ecx: CPUID argument in ecx
> > +# @eax: eax
> > +# @ebx: ebx
> > +# @ecx: ecx
> > +# @edx: edx
> > +#
> > +# Since: 6.1
> > +##
> > +{ 'struct': 'CpuidEntry',
> > +  'data': { 'in_eax' : 'uint32',
> > +'*in_ecx' : 'uint32',
> > +'eax' : 'uint32',
> > +'ebx' : 'uint32',
> > +'ecx' : 'uint32',
> > +'edx' : 'uint32'
> > +  },
> > +  'if': 

Re: [PATCH v2 04/28] softfloat: Move minmax_flags to softfloat-parts.c.inc

2021-06-02 Thread Alex Bennée


Richard Henderson  writes:

> Rename to parts$N_minmax.  Combine 3 bool arguments to a bitmask,
> return a tri-state value to indicate nan vs unchanged operand.
> Introduce ftype_minmax functions as a common optimization point.
> Fold bfloat16 expansions into the same macro as the other types.
>
> Signed-off-by: Richard Henderson 
> ---

> -switch (a.cls) {
> -case float_class_normal:
> -a_exp = a.exp;
> -break;
> -case float_class_inf:
> -a_exp = INT_MAX;
> -break;
> -case float_class_zero:
> -a_exp = INT_MIN;
> -break;
> -default:
> -g_assert_not_reached();
> -break;
> -}
> -switch (b.cls) {
> -case float_class_normal:
> -b_exp = b.exp;
> -break;
> -case float_class_inf:
> -b_exp = INT_MAX;
> -break;
> -case float_class_zero:
> -b_exp = INT_MIN;
> -break;
> -default:
> -g_assert_not_reached();
> -break;
> -}
> -

> +if (unlikely(ab_mask != float_cmask_normal)) {
> +switch (a->cls) {
> +case float_class_normal:
> +break;
> +case float_class_inf:
> +a_exp = INT16_MAX;

We've gone from min/max of our internal representation to INT16_MIN/MAX
- I guess that doesn't break until we get to Float256 but why the change?


-- 
Alex Bennée



Re: [PATCH v2 1/3] doc: Fix some mistakes in the SEV documentation

2021-06-02 Thread Connor Kuehl
On 4/23/21 3:08 PM, Tom Lendacky wrote:
> From: Tom Lendacky 
> 
> Fix some spelling and grammar mistakes in the amd-memory-encryption.txt
> file. No new information added.
> 
> Signed-off-by: Tom Lendacky 

For the series:

Reviewed-by: Connor Kuehl 




Re: [RFC PATCH] target/ppc: fix address translation bug for hash table mmus

2021-06-02 Thread Bruno Piazera Larsen


On 02/06/2021 16:26, Richard Henderson wrote:

On 6/2/21 12:18 PM, Bruno Larsen (billionai) wrote:

Based-on: <20210518201146.794854-1-richard.hender...@linaro.org>

This commit attempts to implement a first draft of a solution to the
first bug mentioned by Richard Henderson in this e-mail
https://lists.nongnu.org/archive/html/qemu-devel/2021-05/msg06247.html
The second bug was not touched, which is basically implementing the
solution C

To sumarize the first bug here, from my understanding, when an address
translation is asked of a 64bit mmu that uses hashtables, the code
attempts to check some permission bits, but checks them from the wrong
location.

The solution implemented here is more complex than necessary on
purpose, to make it more readable (and make sure I understand what is
going on). If that would really fix the problem, I'll move to
implementing an actual solution, and to all affected functions.

Signed-off-by: Bruno Larsen (billionai) 
---
  target/ppc/mmu-hash64.c | 12 ++--
  1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/target/ppc/mmu-hash64.c b/target/ppc/mmu-hash64.c
index c1b98a97e9..63f10f1be7 100644
--- a/target/ppc/mmu-hash64.c
+++ b/target/ppc/mmu-hash64.c
@@ -887,6 +887,14 @@ bool ppc_hash64_xlate(PowerPCCPU *cpu, vaddr 
eaddr, MMUAccessType access_type,

  int exec_prot, pp_prot, amr_prot, prot;
  int need_prot;
  hwaddr raddr;
+    unsigned immu_idx, dmmu_idx;
+    immu_idx = (env->hflags >> HFLAGS_IMMU_IDX) & 7;
+    dmmu_idx = (env->hflags >> HFLAGS_DMMU_IDX) & 7;


This doesn't help at all with the reported bug. You're still reading 
from env. You need the mmu_idx that was passed to ppc_cpu_tlb_fill.
Ah, I saw a macro for MMU_IDX and assumed they pointed to different 
locations. Ok, the fix for ppc_cpu_tlb_fill should be easy, then


For the use from ppc_cpu_get_phys_page_debug, you'd pass in 
cpu_mmu_index(env, false).


ppc_cpu_get_phys_page_debug has 2 calls to ppc_xlate, one using the data 
MMU, the other using the instruction MMU. I'm guessing I should pass 
both, right?


But here we have another bit that confuses me: cpu_mmu_index returns 0 
if in user mode, or uses the information stored in env to get it, so I 
don't see how that would be different from getting directly. Unless the 
point is to have ppc_*_xlate be generic and pc_*_debug knows the info in 
env is correct. Is that it?






+    const short HV = 1, IR = 2, DR = 3;
+    bool MSR[3];
+    MSR[HV] = dmmu_idx & 2,
+    MSR[IR] = immu_idx & 4,
+    MSR[DR] = dmmu_idx & 4;


There's no point in the array.  Just use three different scalars 
(real_mode, hv, and pr (note that pr is the major portion of the bug 
as reported)). Additionally, you'll not be distinguishing immu_idx and 
dmmu_idx, but using the single idx that's given.


Ah, yeah, that's the "more complex than necessary, but it was easy for 
me to read" part. Scalars are a good solution. In this function in 
specific, PR doesn't actually show up anywhere, so I would actually only 
need 2. Anyway, will start working on this.





-    if (access_type == MMU_INST_FETCH ? !msr_ir : !msr_dr) {
+    if (access_type == MMU_INST_FETCH ? !MSR[IR] : !MSR[DR]) {


Which simplifies this condition to just a single test.


r~

--
Bruno Piazera Larsen
Instituto de Pesquisas ELDORADO 


Departamento Computação Embarcada
Analista de Software Trainee
Aviso Legal - Disclaimer 


Re: [PATCH v2 1/3] doc: Fix some mistakes in the SEV documentation

2021-06-02 Thread Tom Lendacky
Just a quick ping on this series...

Thanks,
Tom

On 4/23/21 3:08 PM, Tom Lendacky wrote:
> From: Tom Lendacky 
> 
> Fix some spelling and grammar mistakes in the amd-memory-encryption.txt
> file. No new information added.
> 
> Signed-off-by: Tom Lendacky 
> ---
>  docs/amd-memory-encryption.txt | 59 +-
>  1 file changed, 29 insertions(+), 30 deletions(-)
> 
> diff --git a/docs/amd-memory-encryption.txt b/docs/amd-memory-encryption.txt
> index 145896aec7..ed85159ea7 100644
> --- a/docs/amd-memory-encryption.txt
> +++ b/docs/amd-memory-encryption.txt
> @@ -1,38 +1,38 @@
>  Secure Encrypted Virtualization (SEV) is a feature found on AMD processors.
>  
>  SEV is an extension to the AMD-V architecture which supports running 
> encrypted
> -virtual machine (VMs) under the control of KVM. Encrypted VMs have their 
> pages
> +virtual machines (VMs) under the control of KVM. Encrypted VMs have their 
> pages
>  (code and data) secured such that only the guest itself has access to the
>  unencrypted version. Each encrypted VM is associated with a unique encryption
> -key; if its data is accessed to a different entity using a different key the
> +key; if its data is accessed by a different entity using a different key the
>  encrypted guests data will be incorrectly decrypted, leading to 
> unintelligible
>  data.
>  
> -The key management of this feature is handled by separate processor known as
> -AMD secure processor (AMD-SP) which is present in AMD SOCs. Firmware running
> -inside the AMD-SP provide commands to support common VM lifecycle. This
> +Key management for this feature is handled by a separate processor known as 
> the
> +AMD secure processor (AMD-SP), which is present in AMD SOCs. Firmware running
> +inside the AMD-SP provides commands to support a common VM lifecycle. This
>  includes commands for launching, snapshotting, migrating and debugging the
> -encrypted guest. Those SEV command can be issued via KVM_MEMORY_ENCRYPT_OP
> +encrypted guest. These SEV commands can be issued via KVM_MEMORY_ENCRYPT_OP
>  ioctls.
>  
>  Launching
>  -
> -Boot images (such as bios) must be encrypted before guest can be booted.
> -MEMORY_ENCRYPT_OP ioctl provides commands to encrypt the images 
> :LAUNCH_START,
> +Boot images (such as bios) must be encrypted before a guest can be booted. 
> The
> +MEMORY_ENCRYPT_OP ioctl provides commands to encrypt the images: 
> LAUNCH_START,
>  LAUNCH_UPDATE_DATA, LAUNCH_MEASURE and LAUNCH_FINISH. These four commands
>  together generate a fresh memory encryption key for the VM, encrypt the boot
> -images and provide a measurement than can be used as an attestation of the
> +images and provide a measurement than can be used as an attestation of a
>  successful launch.
>  
>  LAUNCH_START is called first to create a cryptographic launch context within
> -the firmware. To create this context, guest owner must provides guest policy,
> +the firmware. To create this context, guest owner must provide a guest 
> policy,
>  its public Diffie-Hellman key (PDH) and session parameters. These inputs
> -should be treated as binary blob and must be passed as-is to the SEV 
> firmware.
> +should be treated as a binary blob and must be passed as-is to the SEV 
> firmware.
>  
> -The guest policy is passed as plaintext and hypervisor may able to read it
> +The guest policy is passed as plaintext. A hypervisor may choose to read it,
>  but should not modify it (any modification of the policy bits will result
>  in bad measurement). The guest policy is a 4-byte data structure containing
> -several flags that restricts what can be done on running SEV guest.
> +several flags that restricts what can be done on a running SEV guest.
>  See KM Spec section 3 and 6.2 for more details.
>  
>  The guest policy can be provided via the 'policy' property (see below)
> @@ -40,31 +40,30 @@ The guest policy can be provided via the 'policy' 
> property (see below)
>  # ${QEMU} \
> sev-guest,id=sev0,policy=0x1...\
>  
> -Guest owners provided DH certificate and session parameters will be used to
> +The guest owner provided DH certificate and session parameters will be used 
> to
>  establish a cryptographic session with the guest owner to negotiate keys used
>  for the attestation.
>  
> -The DH certificate and session blob can be provided via 'dh-cert-file' and
> -'session-file' property (see below
> +The DH certificate and session blob can be provided via the 'dh-cert-file' 
> and
> +'session-file' properties (see below)
>  
>  # ${QEMU} \
>   sev-guest,id=sev0,dh-cert-file=,session-file=
>  
>  LAUNCH_UPDATE_DATA encrypts the memory region using the cryptographic context
> -created via LAUNCH_START command. If required, this command can be called
> +created via the LAUNCH_START command. If required, this command can be called
>  multiple times to encrypt different memory regions. The command also 
> calculates
>  the measurement of the memory contents as it 

[RFC PATCH 4/4] target/ppc: Moved helpers to mmu_helper.c

2021-06-02 Thread Lucas Mateus Castro (alqotel)
Moved helpers from target/ppc/mmu-hash64.c to target/ppc/mmu_helpers.c
and removed #ifdef CONFIG_TCG and #include exec/helper-proto.h from
mmu-hash64.c

Signed-off-by: Lucas Mateus Castro (alqotel) 
---
I had to turn slb_lookup in a non static function as it had calls from
the code that was moved to mmu_helper.c and from the code that wasn't
moved.

Also perhaps it would be best to create a new file to move the mmu-hash
functions that are not compiled in !TCG, personally I thought that
moving the helpers in mmu-hash64 to mmu_helpers the better choice.
---
 target/ppc/mmu-hash64.c | 219 +---
 target/ppc/mmu-hash64.h |   1 +
 target/ppc/mmu_helper.c | 209 ++
 3 files changed, 211 insertions(+), 218 deletions(-)

diff --git a/target/ppc/mmu-hash64.c b/target/ppc/mmu-hash64.c
index 708dffc31b..d2ded71107 100644
--- a/target/ppc/mmu-hash64.c
+++ b/target/ppc/mmu-hash64.c
@@ -32,10 +32,6 @@
 #include "mmu-book3s-v3.h"
 #include "helper_regs.h"
 
-#ifdef CONFIG_TCG
-#include "exec/helper-proto.h"
-#endif
-
 /* #define DEBUG_SLB */
 
 #ifdef DEBUG_SLB
@@ -48,7 +44,7 @@
  * SLB handling
  */
 
-static ppc_slb_t *slb_lookup(PowerPCCPU *cpu, target_ulong eaddr)
+ppc_slb_t *slb_lookup(PowerPCCPU *cpu, target_ulong eaddr)
 {
 CPUPPCState *env = >env;
 uint64_t esid_256M, esid_1T;
@@ -100,114 +96,6 @@ void dump_slb(PowerPCCPU *cpu)
 }
 }
 
-#ifdef CONFIG_TCG
-void helper_slbia(CPUPPCState *env, uint32_t ih)
-{
-PowerPCCPU *cpu = env_archcpu(env);
-int starting_entry;
-int n;
-
-/*
- * slbia must always flush all TLB (which is equivalent to ERAT in ppc
- * architecture). Matching on SLB_ESID_V is not good enough, because slbmte
- * can overwrite a valid SLB without flushing its lookaside information.
- *
- * It would be possible to keep the TLB in synch with the SLB by flushing
- * when a valid entry is overwritten by slbmte, and therefore slbia would
- * not have to flush unless it evicts a valid SLB entry. However it is
- * expected that slbmte is more common than slbia, and slbia is usually
- * going to evict valid SLB entries, so that tradeoff is unlikely to be a
- * good one.
- *
- * ISA v2.05 introduced IH field with values 0,1,2,6. These all invalidate
- * the same SLB entries (everything but entry 0), but differ in what
- * "lookaside information" is invalidated. TCG can ignore this and flush
- * everything.
- *
- * ISA v3.0 introduced additional values 3,4,7, which change what SLBs are
- * invalidated.
- */
-
-env->tlb_need_flush |= TLB_NEED_LOCAL_FLUSH;
-
-starting_entry = 1; /* default for IH=0,1,2,6 */
-
-if (env->mmu_model == POWERPC_MMU_3_00) {
-switch (ih) {
-case 0x7:
-/* invalidate no SLBs, but all lookaside information */
-return;
-
-case 0x3:
-case 0x4:
-/* also considers SLB entry 0 */
-starting_entry = 0;
-break;
-
-case 0x5:
-/* treat undefined values as ih==0, and warn */
-qemu_log_mask(LOG_GUEST_ERROR,
-  "slbia undefined IH field %u.\n", ih);
-break;
-
-default:
-/* 0,1,2,6 */
-break;
-}
-}
-
-for (n = starting_entry; n < cpu->hash64_opts->slb_size; n++) {
-ppc_slb_t *slb = >slb[n];
-
-if (!(slb->esid & SLB_ESID_V)) {
-continue;
-}
-if (env->mmu_model == POWERPC_MMU_3_00) {
-if (ih == 0x3 && (slb->vsid & SLB_VSID_C) == 0) {
-/* preserves entries with a class value of 0 */
-continue;
-}
-}
-
-slb->esid &= ~SLB_ESID_V;
-}
-}
-
-static void __helper_slbie(CPUPPCState *env, target_ulong addr,
-   target_ulong global)
-{
-PowerPCCPU *cpu = env_archcpu(env);
-ppc_slb_t *slb;
-
-slb = slb_lookup(cpu, addr);
-if (!slb) {
-return;
-}
-
-if (slb->esid & SLB_ESID_V) {
-slb->esid &= ~SLB_ESID_V;
-
-/*
- * XXX: given the fact that segment size is 256 MB or 1TB,
- *  and we still don't have a tlb_flush_mask(env, n, mask)
- *  in QEMU, we just invalidate all TLBs
- */
-env->tlb_need_flush |=
-(global == false ? TLB_NEED_LOCAL_FLUSH : TLB_NEED_GLOBAL_FLUSH);
-}
-}
-
-void helper_slbie(CPUPPCState *env, target_ulong addr)
-{
-__helper_slbie(env, addr, false);
-}
-
-void helper_slbieg(CPUPPCState *env, target_ulong addr)
-{
-__helper_slbie(env, addr, true);
-}
-#endif
-
 int ppc_store_slb(PowerPCCPU *cpu, target_ulong slot,
   target_ulong esid, target_ulong vsid)
 {
@@ -260,102 +148,6 @@ int ppc_store_slb(PowerPCCPU *cpu, target_ulong slot,
 return 0;
 }
 
-#ifdef CONFIG_TCG
-static int ppc_load_slb_esid(PowerPCCPU *cpu, target_ulong rb,
-   

[RFC PATCH 2/4] target/ppc: divided mmu_helper.c in 2 files

2021-06-02 Thread Lucas Mateus Castro (alqotel)
Moved functions in mmu_helper.c that should be compiled in build to
mmu_common.c, moved declaration of functions that both files use to
cpu.h and moved struct declarations and inline functions needed by
both to target/ppc/internal.h. Updated meson.build to compile the
new file.

Signed-off-by: Lucas Mateus Castro (alqotel) 
---
Had to turn a few functions non static as it was used by both
mmu_common.c and mmu_helper.c. Added the declaration of mmu_ctx_t to
cpu.h so functions there can reference it and added the definition to
internal.h so functions in both mmu_* files can access it.
And maybe the tlb functions should be declared in internal.h instead of
cpu.h.
---
 target/ppc/cpu.h|   35 +
 target/ppc/internal.h   |   26 +
 target/ppc/meson.build  |6 +-
 target/ppc/mmu_common.c | 1606 ++
 target/ppc/mmu_helper.c | 1814 +++
 5 files changed, 1774 insertions(+), 1713 deletions(-)
 create mode 100644 target/ppc/mmu_common.c

diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h
index b0934d9be4..cfc35ef83e 100644
--- a/target/ppc/cpu.h
+++ b/target/ppc/cpu.h
@@ -1329,6 +1329,41 @@ void store_booke_tsr(CPUPPCState *env, target_ulong val);
 void ppc_tlb_invalidate_all(CPUPPCState *env);
 void ppc_tlb_invalidate_one(CPUPPCState *env, target_ulong addr);
 void cpu_ppc_set_vhyp(PowerPCCPU *cpu, PPCVirtualHypervisor *vhyp);
+
+typedef struct mmu_ctx_t mmu_ctx_t;
+int ppcemb_tlb_check(CPUPPCState *env, ppcemb_tlb_t *tlb,
+hwaddr *raddrp,
+target_ulong address, uint32_t pid, int ext,
+int i);
+int get_physical_address_wtlb(CPUPPCState *env, mmu_ctx_t *ctx,
+ target_ulong eaddr,
+ MMUAccessType access_type, int type,
+ int mmu_idx);
+hwaddr booke206_tlb_to_page_size(CPUPPCState *env,
+ppcmas_tlb_t *tlb);
+int ppcmas_tlb_check(CPUPPCState *env, ppcmas_tlb_t *tlb,
+hwaddr *raddrp, target_ulong address,
+uint32_t pid);
+int get_physical_address(CPUPPCState *env, mmu_ctx_t *ctx,
+target_ulong eaddr, MMUAccessType access_type,
+int type);
+static inline int ppc6xx_tlb_getnum(CPUPPCState *env, target_ulong eaddr,
+int way, int is_code)
+{
+int nr;
+
+/* Select TLB num in a way from address */
+nr = (eaddr >> TARGET_PAGE_BITS) & (env->tlb_per_way - 1);
+/* Select TLB way */
+nr += env->tlb_per_way * way;
+/* 6xx have separate TLBs for instructions and data */
+if (is_code && env->id_tlbs == 1) {
+nr += env->nb_tlb;
+}
+
+return nr;
+}
+
 #endif
 #endif
 
diff --git a/target/ppc/internal.h b/target/ppc/internal.h
index 2b4b06eb76..7d2913ec28 100644
--- a/target/ppc/internal.h
+++ b/target/ppc/internal.h
@@ -247,4 +247,30 @@ static inline int prot_for_access_type(MMUAccessType 
access_type)
 g_assert_not_reached();
 }
 
+/* Context used internally during MMU translations */
+
+struct mmu_ctx_t {
+hwaddr raddr;  /* Real address  */
+hwaddr eaddr;  /* Effective address */
+int prot;  /* Protection bits   */
+hwaddr hash[2];/* Pagetable hash values */
+target_ulong ptem; /* Virtual segment ID | API  */
+int key;   /* Access key*/
+int nx;/* Non-execute area  */
+};
+
+/* Common routines used by software and hardware TLBs emulation */
+static inline int pte_is_valid(target_ulong pte0)
+{
+return pte0 & 0x8000 ? 1 : 0;
+}
+
+static inline void pte_invalidate(target_ulong *pte0)
+{
+*pte0 &= ~0x8000;
+}
+
+#define PTE_PTEM_MASK 0x7FBF
+#define PTE_CHECK_MASK (TARGET_PAGE_MASK | 0x7B)
+
 #endif /* PPC_INTERNAL_H */
diff --git a/target/ppc/meson.build b/target/ppc/meson.build
index a6a53a8d5c..a54445d0da 100644
--- a/target/ppc/meson.build
+++ b/target/ppc/meson.build
@@ -28,10 +28,12 @@ ppc_softmmu_ss.add(files(
   'arch_dump.c',
   'machine.c',
   'mmu-hash32.c',
-  'mmu_helper.c',
+  'mmu_common.c',
   'monitor.c',
 ))
-ppc_softmmu_ss.add(when: 'CONFIG_TCG', if_false: files(
+ppc_softmmu_ss.add(when: 'CONFIG_TCG', if_true: files(
+  'mmu_helper.c',
+), if_false: files(
   'tcg-stub.c'
 ))
 
diff --git a/target/ppc/mmu_common.c b/target/ppc/mmu_common.c
new file mode 100644
index 00..d95399d67f
--- /dev/null
+++ b/target/ppc/mmu_common.c
@@ -0,0 +1,1606 @@
+/*
+ *  PowerPC CPU initialization for qemu.
+ *
+ *  Copyright (C) 2021 Instituto de Pesquisas Eldorado (eldorado.org.br)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published 

[RFC PATCH 3/4] target/ppc: moved ppc_store_sdr1 to mmu_common.c

2021-06-02 Thread Lucas Mateus Castro (alqotel)
Moved ppc_store_sdr1 to mmu_common.c as it was originally in
mmu_helper.c.

Signed-off-by: Lucas Mateus Castro (alqotel) 
---
Talking to billionai he commented that ppc_store_sdr1 was at first in
mmu_helper.c and was moved as part of the patches to enable the
disable-tcg option, now it's being moved back to a file that will be
compiled in a !TCG build.
---
 target/ppc/cpu.c| 28 
 target/ppc/mmu_common.c | 28 
 2 files changed, 28 insertions(+), 28 deletions(-)

diff --git a/target/ppc/cpu.c b/target/ppc/cpu.c
index c8e87e30f1..5ff00a6c01 100644
--- a/target/ppc/cpu.c
+++ b/target/ppc/cpu.c
@@ -66,34 +66,6 @@ uint32_t ppc_get_vscr(CPUPPCState *env)
 return env->vscr | (sat << VSCR_SAT);
 }
 
-#ifdef CONFIG_SOFTMMU
-void ppc_store_sdr1(CPUPPCState *env, target_ulong value)
-{
-PowerPCCPU *cpu = env_archcpu(env);
-qemu_log_mask(CPU_LOG_MMU, "%s: " TARGET_FMT_lx "\n", __func__, value);
-assert(!cpu->vhyp);
-#if defined(TARGET_PPC64)
-if (mmu_is_64bit(env->mmu_model)) {
-target_ulong sdr_mask = SDR_64_HTABORG | SDR_64_HTABSIZE;
-target_ulong htabsize = value & SDR_64_HTABSIZE;
-
-if (value & ~sdr_mask) {
-qemu_log_mask(LOG_GUEST_ERROR, "Invalid bits 0x"TARGET_FMT_lx
- " set in SDR1", value & ~sdr_mask);
-value &= sdr_mask;
-}
-if (htabsize > 28) {
-qemu_log_mask(LOG_GUEST_ERROR, "Invalid HTABSIZE 0x" TARGET_FMT_lx
- " stored in SDR1", htabsize);
-return;
-}
-}
-#endif /* defined(TARGET_PPC64) */
-/* FIXME: Should check for valid HTABMASK values in 32-bit case */
-env->spr[SPR_SDR1] = value;
-}
-#endif /* CONFIG_SOFTMMU */
-
 /* GDBstub can read and write MSR... */
 void ppc_store_msr(CPUPPCState *env, target_ulong value)
 {
diff --git a/target/ppc/mmu_common.c b/target/ppc/mmu_common.c
index d95399d67f..50b8799d71 100644
--- a/target/ppc/mmu_common.c
+++ b/target/ppc/mmu_common.c
@@ -58,6 +58,34 @@
 #  define LOG_BATS(...) do { } while (0)
 #endif
 
+#ifdef CONFIG_SOFTMMU
+void ppc_store_sdr1(CPUPPCState *env, target_ulong value)
+{
+PowerPCCPU *cpu = env_archcpu(env);
+qemu_log_mask(CPU_LOG_MMU, "%s: " TARGET_FMT_lx "\n", __func__, value);
+assert(!cpu->vhyp);
+#if defined(TARGET_PPC64)
+if (mmu_is_64bit(env->mmu_model)) {
+target_ulong sdr_mask = SDR_64_HTABORG | SDR_64_HTABSIZE;
+target_ulong htabsize = value & SDR_64_HTABSIZE;
+
+if (value & ~sdr_mask) {
+qemu_log_mask(LOG_GUEST_ERROR, "Invalid bits 0x"TARGET_FMT_lx
+ " set in SDR1", value & ~sdr_mask);
+value &= sdr_mask;
+}
+if (htabsize > 28) {
+qemu_log_mask(LOG_GUEST_ERROR, "Invalid HTABSIZE 0x" TARGET_FMT_lx
+ " stored in SDR1", htabsize);
+return;
+}
+}
+#endif /* defined(TARGET_PPC64) */
+/* FIXME: Should check for valid HTABMASK values in 32-bit case */
+env->spr[SPR_SDR1] = value;
+}
+#endif /* CONFIG_SOFTMMU */
+
 /*/
 /* PowerPC MMU emulation */
 
-- 
2.17.1




[RFC PATCH 1/4] target/ppc: Don't compile ppc_tlb_invalid_all without TCG

2021-06-02 Thread Lucas Mateus Castro (alqotel)
The function ppc_tlb_invalid_all is not compiled anymore in a TCG-less
environment, and the call to that function has been disabled in this
situation.

Signed-off-by: Lucas Mateus Castro (alqotel) 
---
Is there a better way than to deal with the
ppc_tlb_invalidate_all call than ifdef? I couldn't think of one.
---
 target/ppc/cpu_init.c   | 4 
 target/ppc/mmu_helper.c | 4 
 2 files changed, 8 insertions(+)

diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c
index 74a397ad6c..2051f24467 100644
--- a/target/ppc/cpu_init.c
+++ b/target/ppc/cpu_init.c
@@ -9114,7 +9114,11 @@ static void ppc_cpu_reset(DeviceState *dev)
 #if !defined(CONFIG_USER_ONLY)
 env->nip = env->hreset_vector | env->excp_prefix;
 if (env->mmu_model != POWERPC_MMU_REAL) {
+#if defined(CONFIG_TCG)
 ppc_tlb_invalidate_all(env);
+#else
+   cpu_abort(env_cpu(env),"PowerPC not in real mode, invalid in this 
build\n");
+#endif
 }
 #endif
 
diff --git a/target/ppc/mmu_helper.c b/target/ppc/mmu_helper.c
index 1ecb36e85a..803b66f2b0 100644
--- a/target/ppc/mmu_helper.c
+++ b/target/ppc/mmu_helper.c
@@ -825,6 +825,7 @@ static int mmubooke_get_physical_address(CPUPPCState *env, 
mmu_ctx_t *ctx,
 return ret;
 }
 
+#ifdef CONFIG_TCG
 static void booke206_flush_tlb(CPUPPCState *env, int flags,
const int check_iprot)
 {
@@ -846,6 +847,7 @@ static void booke206_flush_tlb(CPUPPCState *env, int flags,
 
 tlb_flush(env_cpu(env));
 }
+#endif
 
 static hwaddr booke206_tlb_to_page_size(CPUPPCState *env,
 ppcmas_tlb_t *tlb)
@@ -1952,6 +1954,7 @@ void helper_store_601_batl(CPUPPCState *env, uint32_t nr, 
target_ulong value)
 }
 #endif
 
+#ifdef CONFIG_TCG
 /*/
 /* TLB management */
 void ppc_tlb_invalidate_all(CPUPPCState *env)
@@ -1995,6 +1998,7 @@ void ppc_tlb_invalidate_all(CPUPPCState *env)
 break;
 }
 }
+#endif
 
 #ifdef CONFIG_TCG
 void ppc_tlb_invalidate_one(CPUPPCState *env, target_ulong addr)
-- 
2.17.1




[RFC PATCH 0/4] target/ppc: mmu cleanup

2021-06-02 Thread Lucas Mateus Castro (alqotel)
This patch series aims to clean up some of the code in mmu-hash64.c and
mmu_helper.c, including removing the includes inside ifdef of those
files.

Helpers are in mmu_helper.c now and code that is needed in a !TCG build
are in mmu-hash64.c and mmu_common.c.

Comments are welcome, thanks,
Lucas Mateus.
Based-on: 558f3e1031caf539b74d2891f6a8fb491735a1ac

Lucas Mateus Castro (alqotel) (4):
  target/ppc: Don't compile ppc_tlb_invalid_all without TCG
  target/ppc: divided mmu_helper.c in 2 files
  target/ppc: moved ppc_store_sdr1 to mmu_common.c
  target/ppc: Moved helpers to mmu_helper.c

 target/ppc/cpu.c|   28 -
 target/ppc/cpu.h|   35 +
 target/ppc/cpu_init.c   |4 +
 target/ppc/internal.h   |   26 +
 target/ppc/meson.build  |6 +-
 target/ppc/mmu-hash64.c |  219 +
 target/ppc/mmu-hash64.h |1 +
 target/ppc/mmu_common.c | 1634 +++
 target/ppc/mmu_helper.c | 2023 ++-
 9 files changed, 2019 insertions(+), 1957 deletions(-)
 create mode 100644 target/ppc/mmu_common.c

-- 
2.17.1




Re: [RFC PATCH] target/ppc: fix address translation bug for hash table mmus

2021-06-02 Thread Richard Henderson

On 6/2/21 12:18 PM, Bruno Larsen (billionai) wrote:

Based-on: <20210518201146.794854-1-richard.hender...@linaro.org>

This commit attempts to implement a first draft of a solution to the
first bug mentioned by Richard Henderson in this e-mail
https://lists.nongnu.org/archive/html/qemu-devel/2021-05/msg06247.html
The second bug was not touched, which is basically implementing the
solution C

To sumarize the first bug here, from my understanding, when an address
translation is asked of a 64bit mmu that uses hashtables, the code
attempts to check some permission bits, but checks them from the wrong
location.

The solution implemented here is more complex than necessary on
purpose, to make it more readable (and make sure I understand what is
going on). If that would really fix the problem, I'll move to
implementing an actual solution, and to all affected functions.

Signed-off-by: Bruno Larsen (billionai) 
---
  target/ppc/mmu-hash64.c | 12 ++--
  1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/target/ppc/mmu-hash64.c b/target/ppc/mmu-hash64.c
index c1b98a97e9..63f10f1be7 100644
--- a/target/ppc/mmu-hash64.c
+++ b/target/ppc/mmu-hash64.c
@@ -887,6 +887,14 @@ bool ppc_hash64_xlate(PowerPCCPU *cpu, vaddr eaddr, 
MMUAccessType access_type,
  int exec_prot, pp_prot, amr_prot, prot;
  int need_prot;
  hwaddr raddr;
+unsigned immu_idx, dmmu_idx;
+immu_idx = (env->hflags >> HFLAGS_IMMU_IDX) & 7;
+dmmu_idx = (env->hflags >> HFLAGS_DMMU_IDX) & 7;


This doesn't help at all with the reported bug. You're still reading from env. 
You need the mmu_idx that was passed to ppc_cpu_tlb_fill.


For the use from ppc_cpu_get_phys_page_debug, you'd pass in cpu_mmu_index(env, 
false).




+const short HV = 1, IR = 2, DR = 3;
+bool MSR[3];
+MSR[HV] = dmmu_idx & 2,
+MSR[IR] = immu_idx & 4,
+MSR[DR] = dmmu_idx & 4;


There's no point in the array.  Just use three different scalars (real_mode, 
hv, and pr (note that pr is the major portion of the bug as reported)). 
Additionally, you'll not be distinguishing immu_idx and dmmu_idx, but using the 
single idx that's given.



-if (access_type == MMU_INST_FETCH ? !msr_ir : !msr_dr) {
+if (access_type == MMU_INST_FETCH ? !MSR[IR] : !MSR[DR]) {


Which simplifies this condition to just a single test.


r~



[RFC PATCH] target/ppc: fix address translation bug for hash table mmus

2021-06-02 Thread Bruno Larsen (billionai)
Based-on: <20210518201146.794854-1-richard.hender...@linaro.org>

This commit attempts to implement a first draft of a solution to the
first bug mentioned by Richard Henderson in this e-mail
https://lists.nongnu.org/archive/html/qemu-devel/2021-05/msg06247.html
The second bug was not touched, which is basically implementing the
solution C

To sumarize the first bug here, from my understanding, when an address
translation is asked of a 64bit mmu that uses hashtables, the code
attempts to check some permission bits, but checks them from the wrong
location.

The solution implemented here is more complex than necessary on
purpose, to make it more readable (and make sure I understand what is
going on). If that would really fix the problem, I'll move to
implementing an actual solution, and to all affected functions.

Signed-off-by: Bruno Larsen (billionai) 
---
 target/ppc/mmu-hash64.c | 12 ++--
 1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/target/ppc/mmu-hash64.c b/target/ppc/mmu-hash64.c
index c1b98a97e9..63f10f1be7 100644
--- a/target/ppc/mmu-hash64.c
+++ b/target/ppc/mmu-hash64.c
@@ -887,6 +887,14 @@ bool ppc_hash64_xlate(PowerPCCPU *cpu, vaddr eaddr, 
MMUAccessType access_type,
 int exec_prot, pp_prot, amr_prot, prot;
 int need_prot;
 hwaddr raddr;
+unsigned immu_idx, dmmu_idx;
+immu_idx = (env->hflags >> HFLAGS_IMMU_IDX) & 7;
+dmmu_idx = (env->hflags >> HFLAGS_DMMU_IDX) & 7;
+const short HV = 1, IR = 2, DR = 3;
+bool MSR[3];
+MSR[HV] = dmmu_idx & 2,
+MSR[IR] = immu_idx & 4,
+MSR[DR] = dmmu_idx & 4;
 
 /*
  * Note on LPCR usage: 970 uses HID4, but our special variant of
@@ -897,7 +905,7 @@ bool ppc_hash64_xlate(PowerPCCPU *cpu, vaddr eaddr, 
MMUAccessType access_type,
  */
 
 /* 1. Handle real mode accesses */
-if (access_type == MMU_INST_FETCH ? !msr_ir : !msr_dr) {
+if (access_type == MMU_INST_FETCH ? !MSR[IR] : !MSR[DR]) {
 /*
  * Translation is supposedly "off", but in real mode the top 4
  * effective address bits are (mostly) ignored
@@ -909,7 +917,7 @@ bool ppc_hash64_xlate(PowerPCCPU *cpu, vaddr eaddr, 
MMUAccessType access_type,
  * In virtual hypervisor mode, there's nothing to do:
  *   EA == GPA == qemu guest address
  */
-} else if (msr_hv || !env->has_hv_mode) {
+} else if (MSR[HV] || !env->has_hv_mode) {
 /* In HV mode, add HRMOR if top EA bit is clear */
 if (!(eaddr >> 63)) {
 raddr |= env->spr[SPR_HRMOR];
-- 
2.17.1




Re: [PATCH v3] target/riscv: fix VS interrupts forwarding to HS

2021-06-02 Thread Jose Martins
Hello Zhiwei and Alistair,

I went for a middle-ground solution. I divided the patch into two: one
fixes the vs interrupt forwarding to the hypervisor, the other removes
the unnecessary force exception stuff. I just submitted the patch
series. I hope it's ok with you.

José

On Fri, 28 May 2021 at 01:36, LIU Zhiwei  wrote:
>
>
> On 5/28/21 6:34 AM, Alistair Francis wrote:
> > On Sun, May 23, 2021 at 1:45 AM Jose Martins  
> > wrote:
> >> VS interrupts (2, 6, 10) were not correctly forwarded to hs-mode when
> >> not delegated in hideleg (which was not being taken into account). This
> >> was mainly because hs level sie was not always considered enabled when
> >> it should. The spec states that "Interrupts for higher-privilege modes,
> >> y>x, are always globally enabled regardless of the setting of the global
> >> yIE bit for the higher-privilege mode." and also "For purposes of
> >> interrupt global enables, HS-mode is considered more privileged than
> >> VS-mode, and VS-mode is considered more privileged than VU-mode".
> >>
> >> These interrupts should be treated the same as any other kind of
> >> exception. Therefore, there is no need to "force an hs exception" as the
> >> current privilege level, the state of the global ie and of the
> >> delegation registers should be enough to route the interrupt to the
> >> appropriate privilege level in riscv_cpu_do_interrupt. Also, these
> >> interrupts never target m-mode, which is  guaranteed by the hardwiring
> >> of the corresponding bits in mideleg. The same is true for synchronous
> >> exceptions, specifically, guest page faults which must be hardwired in
> >> to zero hedeleg. As such the hs_force_except mechanism can be removed.
> >>
> >> Signed-off-by: Jose Martins 
> > This looks right to me, but this was one of the most confusing parts
> > of the implementation. I also don't think the patch is too long as
> > it's mostly just deleting stuff.
> >
> > I don't fully understand your concerns Zhiwei, do you mind stating them 
> > again?
>
> Hi Alistair,
>
> My main concern is the commit message is to complex.
>
> I also have a question why force hs exception in current code.
> Then we can give a brief commit message.
>
> Best Regards,
> Zhiwei
>
> >
> > Alistair
> >
> >> ---
> >> This version of the patch also removes the uneeded hs_force_except
> >> functions, variables and macro.
> >>
> >>   target/riscv/cpu.h|  2 --
> >>   target/riscv/cpu_bits.h   |  6 -
> >>   target/riscv/cpu_helper.c | 54 +++
> >>   3 files changed, 9 insertions(+), 53 deletions(-)
> >>
> >> diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
> >> index 0a33d387ba..a30a64241a 100644
> >> --- a/target/riscv/cpu.h
> >> +++ b/target/riscv/cpu.h
> >> @@ -337,8 +337,6 @@ bool riscv_cpu_exec_interrupt(CPUState *cs, int 
> >> interrupt_request);
> >>   bool riscv_cpu_fp_enabled(CPURISCVState *env);
> >>   bool riscv_cpu_virt_enabled(CPURISCVState *env);
> >>   void riscv_cpu_set_virt_enabled(CPURISCVState *env, bool enable);
> >> -bool riscv_cpu_force_hs_excep_enabled(CPURISCVState *env);
> >> -void riscv_cpu_set_force_hs_excep(CPURISCVState *env, bool enable);
> >>   bool riscv_cpu_two_stage_lookup(int mmu_idx);
> >>   int riscv_cpu_mmu_index(CPURISCVState *env, bool ifetch);
> >>   hwaddr riscv_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
> >> diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h
> >> index caf4599207..7322f54157 100644
> >> --- a/target/riscv/cpu_bits.h
> >> +++ b/target/riscv/cpu_bits.h
> >> @@ -462,12 +462,6 @@
> >>
> >>   /* Virtulisation Register Fields */
> >>   #define VIRT_ONOFF  1
> >> -/* This is used to save state for when we take an exception. If this is 
> >> set
> >> - * that means that we want to force a HS level exception (no matter what 
> >> the
> >> - * delegation is set to). This will occur for things such as a second 
> >> level
> >> - * page table fault.
> >> - */
> >> -#define FORCE_HS_EXCEP  2
> >>
> >>   /* RV32 satp CSR field masks */
> >>   #define SATP32_MODE 0x8000
> >> diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
> >> index 21c54ef561..babe3d844b 100644
> >> --- a/target/riscv/cpu_helper.c
> >> +++ b/target/riscv/cpu_helper.c
> >> @@ -38,36 +38,24 @@ int riscv_cpu_mmu_index(CPURISCVState *env, bool 
> >> ifetch)
> >>   #ifndef CONFIG_USER_ONLY
> >>   static int riscv_cpu_local_irq_pending(CPURISCVState *env)
> >>   {
> >> -target_ulong irqs;
> >> +target_ulong virt_enabled = riscv_cpu_virt_enabled(env);
> >>
> >>   target_ulong mstatus_mie = get_field(env->mstatus, MSTATUS_MIE);
> >>   target_ulong mstatus_sie = get_field(env->mstatus, MSTATUS_SIE);
> >> -target_ulong hs_mstatus_sie = get_field(env->mstatus_hs, MSTATUS_SIE);
> >>
> >> -target_ulong pending = env->mip & env->mie &
> >> -   ~(MIP_VSSIP | MIP_VSTIP | MIP_VSEIP);
> >> -target_ulong vspending = (env->mip & env->mie &
> 

Re: [PATCH v3 09/33] block/nbd: bs-independent interface for nbd_co_establish_connection()

2021-06-02 Thread Eric Blake
On Fri, Apr 16, 2021 at 11:08:47AM +0300, Vladimir Sementsov-Ogievskiy wrote:
> We are going to split connection code to separate file. Now we are

to a separate

> ready to give nbd_co_establish_connection() clean and bs-independent
> interface.
> 
> Signed-off-by: Vladimir Sementsov-Ogievskiy 
> Reviewed-by: Roman Kagan 
> ---
>  block/nbd.c | 49 +++--
>  1 file changed, 31 insertions(+), 18 deletions(-)
> 

> -static int coroutine_fn
> -nbd_co_establish_connection(BlockDriverState *bs, Error **errp)
> +/*
> + * Get a new connection in context of @thr:
> + *   if thread is running, wait for completion

if the thread is running,...

> + *   if thread is already succeeded in background, and user didn't get the

if the thread already succeeded in the background,...

> + * result, just return it now
> + *   otherwise if thread is not running, start a thread and wait for 
> completion

otherwise, the thread is not running, so start...

> + */
> +static coroutine_fn QIOChannelSocket *
> +nbd_co_establish_connection(NBDConnectThread *thr, Error **errp)
>  {
> +QIOChannelSocket *sioc = NULL;
>  QemuThread thread;
> -BDRVNBDState *s = bs->opaque;
> -NBDConnectThread *thr = s->connect_thread;
> -
> -assert(!s->sioc);
>  
>  qemu_mutex_lock(>mutex);
>  
> +/*
> + * Don't call nbd_co_establish_connection() in several coroutines in
> + * parallel. Only one call at once is supported.
> + */
> +assert(!thr->wait_co);
> +
>  if (!thr->running) {
>  if (thr->sioc) {
>  /* Previous attempt finally succeeded in background */
> -goto out;
> +sioc = g_steal_pointer(>sioc);
> +qemu_mutex_unlock(>mutex);

Worth using QEMU_LOCK_GUARD() here?

> +
> +return sioc;
>  }
> +
>  thr->running = true;
>  error_free(thr->err);
>  thr->err = NULL;

Reviewed-by: Eric Blake 

-- 
Eric Blake, Principal Software Engineer
Red Hat, Inc.   +1-919-301-3266
Virtualization:  qemu.org | libvirt.org




[PATCH 1/2] target/riscv: fix VS interrupts forwarding to HS

2021-06-02 Thread Jose Martins
VS interrupts (2, 6, 10) were not correctly forwarded to hs-mode when
not delegated in hideleg (which was not being taken into account). This
was mainly because hs level sie was not always considered enabled when
it should. The spec states that "Interrupts for higher-privilege modes,
y>x, are always globally enabled regardless of the setting of the global
yIE bit for the higher-privilege mode." and also "For purposes of
interrupt global enables, HS-mode is considered more privileged than
VS-mode, and VS-mode is considered more privileged than VU-mode". Also,
vs-level interrupts were not being taken into account unless V=1, but
should be unless delegated.

Finally, there is no need for a special case for to handle vs interrupts
as the current privilege level, the state of the global ie and of the
delegation registers should be enough to route all interrupts to the
appropriate privilege level in riscv_cpu_do_interrupt.

Signed-off-by: Jose Martins 
---
 target/riscv/cpu_helper.c | 28 
 1 file changed, 8 insertions(+), 20 deletions(-)

diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index 21c54ef561..592d4642be 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -38,36 +38,24 @@ int riscv_cpu_mmu_index(CPURISCVState *env, bool ifetch)
 #ifndef CONFIG_USER_ONLY
 static int riscv_cpu_local_irq_pending(CPURISCVState *env)
 {
-target_ulong irqs;
+target_ulong virt_enabled = riscv_cpu_virt_enabled(env);
 
 target_ulong mstatus_mie = get_field(env->mstatus, MSTATUS_MIE);
 target_ulong mstatus_sie = get_field(env->mstatus, MSTATUS_SIE);
-target_ulong hs_mstatus_sie = get_field(env->mstatus_hs, MSTATUS_SIE);
 
-target_ulong pending = env->mip & env->mie &
-   ~(MIP_VSSIP | MIP_VSTIP | MIP_VSEIP);
-target_ulong vspending = (env->mip & env->mie &
-  (MIP_VSSIP | MIP_VSTIP | MIP_VSEIP));
+target_ulong pending = env->mip & env->mie;
 
 target_ulong mie= env->priv < PRV_M ||
   (env->priv == PRV_M && mstatus_mie);
 target_ulong sie= env->priv < PRV_S ||
   (env->priv == PRV_S && mstatus_sie);
-target_ulong hs_sie = env->priv < PRV_S ||
-  (env->priv == PRV_S && hs_mstatus_sie);
+target_ulong hsie   = virt_enabled || sie;
+target_ulong vsie   = virt_enabled && sie;
 
-if (riscv_cpu_virt_enabled(env)) {
-target_ulong pending_hs_irq = pending & -hs_sie;
-
-if (pending_hs_irq) {
-riscv_cpu_set_force_hs_excep(env, FORCE_HS_EXCEP);
-return ctz64(pending_hs_irq);
-}
-
-pending = vspending;
-}
-
-irqs = (pending & ~env->mideleg & -mie) | (pending &  env->mideleg & -sie);
+target_ulong irqs =
+(pending & ~env->mideleg & -mie) |
+(pending &  env->mideleg & ~env->hideleg & -hsie) |
+(pending &  env->mideleg &  env->hideleg & -vsie);
 
 if (irqs) {
 return ctz64(irqs); /* since non-zero */
-- 
2.30.2




[PATCH 2/2] target/riscv: remove force HS exception

2021-06-02 Thread Jose Martins
There is no need to "force an hs exception" as the current privilege
level, the state of the global ie and of the delegation registers should
be enough to route the interrupt to the appropriate privilege level in
riscv_cpu_do_interrupt. The is true for both asynchronous and
synchronous exceptions, specifically, guest page faults which must be
hardwired to zero hedeleg. As such the hs_force_except mechanism can be
removed.

Signed-off-by: Jose Martins 
---
 target/riscv/cpu.h|  2 --
 target/riscv/cpu_bits.h   |  6 --
 target/riscv/cpu_helper.c | 26 +-
 3 files changed, 1 insertion(+), 33 deletions(-)

diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index 0a33d387ba..a30a64241a 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -337,8 +337,6 @@ bool riscv_cpu_exec_interrupt(CPUState *cs, int 
interrupt_request);
 bool riscv_cpu_fp_enabled(CPURISCVState *env);
 bool riscv_cpu_virt_enabled(CPURISCVState *env);
 void riscv_cpu_set_virt_enabled(CPURISCVState *env, bool enable);
-bool riscv_cpu_force_hs_excep_enabled(CPURISCVState *env);
-void riscv_cpu_set_force_hs_excep(CPURISCVState *env, bool enable);
 bool riscv_cpu_two_stage_lookup(int mmu_idx);
 int riscv_cpu_mmu_index(CPURISCVState *env, bool ifetch);
 hwaddr riscv_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h
index caf4599207..7322f54157 100644
--- a/target/riscv/cpu_bits.h
+++ b/target/riscv/cpu_bits.h
@@ -462,12 +462,6 @@
 
 /* Virtulisation Register Fields */
 #define VIRT_ONOFF  1
-/* This is used to save state for when we take an exception. If this is set
- * that means that we want to force a HS level exception (no matter what the
- * delegation is set to). This will occur for things such as a second level
- * page table fault.
- */
-#define FORCE_HS_EXCEP  2
 
 /* RV32 satp CSR field masks */
 #define SATP32_MODE 0x8000
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index 592d4642be..babe3d844b 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -178,24 +178,6 @@ void riscv_cpu_set_virt_enabled(CPURISCVState *env, bool 
enable)
 env->virt = set_field(env->virt, VIRT_ONOFF, enable);
 }
 
-bool riscv_cpu_force_hs_excep_enabled(CPURISCVState *env)
-{
-if (!riscv_has_ext(env, RVH)) {
-return false;
-}
-
-return get_field(env->virt, FORCE_HS_EXCEP);
-}
-
-void riscv_cpu_set_force_hs_excep(CPURISCVState *env, bool enable)
-{
-if (!riscv_has_ext(env, RVH)) {
-return;
-}
-
-env->virt = set_field(env->virt, FORCE_HS_EXCEP, enable);
-}
-
 bool riscv_cpu_two_stage_lookup(int mmu_idx)
 {
 return mmu_idx & TB_FLAGS_PRIV_HYP_ACCESS_MASK;
@@ -884,7 +866,6 @@ void riscv_cpu_do_interrupt(CPUState *cs)
 
 RISCVCPU *cpu = RISCV_CPU(cs);
 CPURISCVState *env = >env;
-bool force_hs_execp = riscv_cpu_force_hs_excep_enabled(env);
 uint64_t s;
 
 /* cs->exception is 32-bits wide unlike mcause which is XLEN-bits wide
@@ -913,8 +894,6 @@ void riscv_cpu_do_interrupt(CPUState *cs)
 case RISCV_EXCP_INST_GUEST_PAGE_FAULT:
 case RISCV_EXCP_LOAD_GUEST_ACCESS_FAULT:
 case RISCV_EXCP_STORE_GUEST_AMO_ACCESS_FAULT:
-force_hs_execp = true;
-/* fallthrough */
 case RISCV_EXCP_INST_ADDR_MIS:
 case RISCV_EXCP_INST_ACCESS_FAULT:
 case RISCV_EXCP_LOAD_ADDR_MIS:
@@ -973,8 +952,7 @@ void riscv_cpu_do_interrupt(CPUState *cs)
 env->hstatus = set_field(env->hstatus, HSTATUS_GVA, 0);
 }
 
-if (riscv_cpu_virt_enabled(env) && ((hdeleg >> cause) & 1) &&
-!force_hs_execp) {
+if (riscv_cpu_virt_enabled(env) && ((hdeleg >> cause) & 1)) {
 /* Trap to VS mode */
 /*
  * See if we need to adjust cause. Yes if its VS mode interrupt
@@ -996,7 +974,6 @@ void riscv_cpu_do_interrupt(CPUState *cs)
 htval = env->guest_phys_fault_addr;
 
 riscv_cpu_set_virt_enabled(env, 0);
-riscv_cpu_set_force_hs_excep(env, 0);
 } else {
 /* Trap into HS mode */
 env->hstatus = set_field(env->hstatus, HSTATUS_SPV, false);
@@ -1032,7 +1009,6 @@ void riscv_cpu_do_interrupt(CPUState *cs)
 
 /* Trapping to M mode, virt is disabled */
 riscv_cpu_set_virt_enabled(env, 0);
-riscv_cpu_set_force_hs_excep(env, 0);
 }
 
 s = env->mstatus;
-- 
2.30.2




[PATCH 0/2] target/riscv: fix hypervisor exceptions

2021-06-02 Thread Jose Martins
This patch series fixes the forwarding of VS-level execptions to HS-mode and
removes unecessary code previously used for the routing of exceptions to
HS-mode.

Jose Martins (2):
  target/riscv: fix VS interrupts forwarding to HS
  target/riscv: remove force HS exception

 target/riscv/cpu.h|  2 --
 target/riscv/cpu_bits.h   |  6 -
 target/riscv/cpu_helper.c | 54 +++
 3 files changed, 9 insertions(+), 53 deletions(-)

-- 
2.30.2




Re: [RFC] Adding the A64FX's HPC funtions.

2021-06-02 Thread Peter Maydell
On Wed, 2 Jun 2021 at 20:02, Richard Henderson
 wrote:
> On 6/1/21 8:21 AM, Peter Maydell wrote:
> >>> 2) Is it OK to specify the option to set the HPC extension of A64FX as 
> >>> follows,
> >>> for example?
> >>>
> >>> -M virt -cpu max,a64fx-hpc-sec=on (*sector cache function) -M virt -cpu
> >>> max,a64fx-hpc-hwpf=on (*hardware prefetvh assist function) -M virt -cpu
> >>> max,a64fx-hpc-hwb=on (*hardware barrier function)
> >>>
> >>> It is also possible to implement something like -cpu a64fx, but since we 
> >>> don't
> >>> know if we can implement it immediately, we assume that we will use the 
> >>> -cpu
> >>> max option first.
>
> My first thought is that -cpu max can simply enable the extensions, without
> extra flags.  The max cpu has all of the features that we can enable, and as I
> see it this is just one more.

I dunno, because it's not an architectural feature, it's an implementation
feature. We can rely on architectural features not to step on each others'
toes, but there's no guarantee that some other impdef feature might not
clash with these a64fx ones.

Also, how does the guest OS typically detect the presence of these
features? If it does it by looking for MIDR etc values that say
"this is an A64FX" then -cpu max won't trigger that.

> I would like to add -cpu a64fx at some point.  But as you say, that need not
> happen right away.

I think it would be worth scoping out how much work the a64fx CPU
would require (ie what else does it need beyond these extensions
and whatever features we currently implement?). If that's not a
lot of work it might be simpler to just add it (possibly even
add it but with one or two of its features as not-yet-implemented.)

thanks
-- PMM



Re: [PATCH v3 07/33] block/nbd: simplify waking of nbd_co_establish_connection()

2021-06-02 Thread Eric Blake
On Fri, Apr 16, 2021 at 11:08:45AM +0300, Vladimir Sementsov-Ogievskiy wrote:

Grammar suggestions:

> Instead of connect_bh, bh_ctx and wait_connect fields we can live with
> only one link to waiting coroutine, protected by mutex.

Instead of managing connect_bh, bh_ctx, and wait_connect fields, we
can use a single link to the waiting coroutine with proper mutex
protection.

> 
> So new logic is:
> 
> nbd_co_establish_connection() sets wait_co under mutex, release the
> mutex and do yield(). Note, that wait_co may be scheduled by thread
> immediately after unlocking the mutex. Still, in main thread (or
> iothread) we'll not reach the code for entering the coroutine until the
> yield() so we are safe.

nbd_co_establish_connection() sets wait_co under the mutex, releases
the mutex, then yield()s.  Note that wait_co may be scheduled by the
thread immediately after unlocking the mutex.  Still, the main thread
(or iothread) will not reach the code for entering the coroutine until
the yield(), so we are safe.

> 
> Both connect_thread_func() and nbd_co_establish_connection_cancel() do
> the following to handle wait_co:
> 
> Under mutex, if thr->wait_co is not NULL, call aio_co_wake() (which
> never tries to acquire aio context since previous commit, so we are
> safe to do it under thr->mutex) and set thr->wait_co to NULL.
> This way we protect ourselves of scheduling it twice.

Under the mutex, if thr_wait_co is not NULL, call aio_co_wake() (the
previous commit ensures it never tries to acquire the aio context, so
we are safe even while under thr->mutex), then sets thr->wait_co to
NULL.  This way, we avoid scheduling the coroutine twice.

> 
> Also this commit make nbd_co_establish_connection() less connected to
> bs (we have generic pointer to the coroutine, not use s->connection_co
> directly). So, we are on the way of splitting connection API out of
> nbd.c (which is overcomplicated now).

Also, this commit reduces the dependence of
nbd_co_establish_connection() on the internals of bs (we now use a
generic pointer to the coroutine, instead of direct use of
s->connection_co).  This is a step towards splitting the connection
API out of nbd.c.

> 
> Signed-off-by: Vladimir Sementsov-Ogievskiy 
> ---
>  block/nbd.c | 49 +
>  1 file changed, 9 insertions(+), 40 deletions(-)
> 

> +++ b/block/nbd.c

> @@ -101,10 +95,10 @@ typedef struct NBDConnectThread {
>  QIOChannelSocket *sioc;
>  Error *err;
>  
> -/* state and bh_ctx are protected by mutex */
>  QemuMutex mutex;
> +/* All further fields are protected by mutex */
>  NBDConnectThreadState state; /* current state of the thread */
> -AioContext *bh_ctx; /* where to schedule bh (NULL means don't schedule) 
> */
> +Coroutine *wait_co; /* nbd_co_establish_connection() wait in yield() */

I'm not sure if that comment is the most legible, but I'm not coming
up with an alternative.  Maybe:

/*
 * if non-NULL, which coroutine to wake in
 * nbd_co_establish_connection() after yield()
 */


But the simplification looks nice, and I didn't spot any obvious
problems with the refactoring.

Reviewed-by: Eric Blake 

-- 
Eric Blake, Principal Software Engineer
Red Hat, Inc.   +1-919-301-3266
Virtualization:  qemu.org | libvirt.org




Re: [RFC] Adding the A64FX's HPC funtions.

2021-06-02 Thread Richard Henderson

On 6/1/21 8:21 AM, Peter Maydell wrote:

I'm thinking of implementing A64FX HPC extension in qemu.
A64FX [1] is a CPU developed by Fujitsu that implements armv8+SVE.

[1]
https://github.com/fujitsu/A64FX/blob/master/doc/A64FX_Microarchitecture
_Manual_en_1.4.pdf

A64FX is a CPU developed for HPC (High Performance Computing), and HPC
extensions [2] are implemented to improve the performance of user programs.

[2]
https://github.com/fujitsu/A64FX/blob/master/doc/A64FX_Specification_HP
C_Extension_v1_EN.pdf

The details of each function are described in [2], and the HPC extensions
include
1) Tag address override
2) Sector cache
3) Hardware barrier
4) Hardware prefetch assist
are implemented.


Thanks for the pointers.  It looks to me that it'll be easy to implement these 
in qemu.  We'll need to implement the registers, so that the OS can read back 
the values, but we do not need to actually do anything with them.



1) Is target/arm/helper.c enough to implement the register (ARMCPRegInfo
structure) of HPC extension function of A64FX?


Yes.


2) Is it OK to specify the option to set the HPC extension of A64FX as follows,
for example?

-M virt -cpu max,a64fx-hpc-sec=on (*sector cache function) -M virt -cpu
max,a64fx-hpc-hwpf=on (*hardware prefetvh assist function) -M virt -cpu
max,a64fx-hpc-hwb=on (*hardware barrier function)

It is also possible to implement something like -cpu a64fx, but since we don't
know if we can implement it immediately, we assume that we will use the -cpu
max option first.


My first thought is that -cpu max can simply enable the extensions, without 
extra flags.  The max cpu has all of the features that we can enable, and as I 
see it this is just one more.


I would like to add -cpu a64fx at some point.  But as you say, that need not 
happen right away.



Since there is no example of A64FX function implemented in QEMU, we would
appreciate your comments before we post a patch.


We endeavor to enable features by the architectural id registers when possible. 
 Thus the cpu_isar_feature() checks in helper.c.


The microarchitectural document provided does not list all of the system 
register reset values for the A64FX, and I would be surprised if there were an 
architectural id register that specified a non-standard extension like this. 
Thus I would expect to add ARM_FEATURE_A64FX with which to enable these 
extensions in helper.c.


I can certainly help you with this.


r~



Re: [PATCH 1/3] virtiofsd: Find original inode ID of mount points

2021-06-02 Thread Miklos Szeredi
On Wed, 2 Jun 2021 at 20:20, Vivek Goyal  wrote:
>
> On Wed, May 12, 2021 at 02:55:42PM +0200, Max Reitz wrote:
> > Mount point directories represent two inodes: On one hand, they are a
> > normal directory on their parent filesystem.  On the other, they are the
> > root node of the filesystem mounted there.  Thus, they have two inode
> > IDs.
> >
> > Right now, we only report the latter inode ID (i.e. the inode ID of the
> > mounted filesystem's root node).  This is fine once the guest has
> > auto-mounted a submount there (so this inode ID goes with a device ID
> > that is distinct from the parent filesystem), but before the auto-mount,
> > they have the device ID of the parent and the inode ID for the submount.
> > This is problematic because this is likely exactly the same
> > st_dev/st_ino combination as the parent filesystem's root node.  This
> > leads to problems for example with `find`, which will thus complain
> > about a filesystem loop if it has visited the parent filesystem's root
> > node before, and then refuse to descend into the submount.
> >
> > There is a way to find the mount directory's original inode ID, and that
> > is to readdir(3) the parent directory, look for the mount directory, and
> > read the dirent.d_ino field.  Using this, we can let lookup and
> > readdirplus return that original inode ID, which the guest will thus
> > show until the submount is auto-mounted.  (Then, it will invoke getattr
> > and that stat(2) call will return the inode ID for the submount.)
>
> [ CC miklos ]
>
> Hi Max,
>
> Though we discussed this in chat room, I am still responding to this
> email with the concern I have, so that there is a record of it.
>
> So with this patch for FUSE_LOOKUP  we always return submount's parentinode
> id and with GETATTR request we return actual inode id of submount. That
> kind of bothers me a bit as we are assuming that there is always going
> to be a GETATTR request after FUSE_LOOKUP. FUSE_LOOKUP itself has attrs
> returned with it and it might happen that after FUSE_LOOKUP, FUSE_GETATTR
> might not be called at all because FUSE_LOOKUP itself got the latest
> updated attrs with certain timeout.
>
> For example, if I call stat on a normal file (not submount), I see that
> after FUSE_LOOKUP, no FUSE_GETATTR request is going and
> fuse_update_get_attr() is using attrs from locally cached inode attrs.
>
> But same thing does not seem to be happening in case of submount. Once
> submount is created in guest, I see that we never seem to be calling
> ->revalidate() on newly created dentry of submount root. I am not sure
> why. And that means we don't do FUSE_LOOKUP and that means FUSE_GETATTR
> always gets called.

Yes, this sounds normal.

The lookup sequence for "/mnt/virtiofs/dir1/submount/file" will be:

LOOKUP(1, "dir")
create inode I1 in sb1
create dentry "dir" with inode I1 in sb1
LOOKUP(I1, "submount")
create inode I2 in sb1, set S_AUTOMOUNT
create dentry "submount" with inode I2 in sb1
automount triggered:
create sb2
create inode I2 in sb2
create dentry "/" with inode I2 in sb2
GETATTR(I2)
 fill inode I2
LOOKUP(I2, "file")
 create inode I3
 create dentry "file" with inode I3 in sb2

Notice how there's two inodes numbered I2, but in separate sb's.
However the server has only the notion of a single I2 inode which is
the root of the submount, since the mountpoint is not visible (except
for d_ino in readdir()).

Now AFAICS what this patch does is set the inode number in the
attributes returned by LOOKUP(I1, "submount") to the covered inode, so
that AT_NO_AUTOMOUNT stat will return the correct value.   While this
seems to work, it's not a fundamental fix to the problem, since the
attributes on sb1/I2 will time out and the next stat(...,
AT_NO_AUTOMOUNT) will trigger a GETATTR request, which will return the
inode number of the submount root.

Solving this properly would mean that the server would have to
generate separate nodeid's for the mountpoint and the submount root
and the protocol would have to be extended so that this information
could be transferred to the client.

Not sure whether this is worth it or not.

Thanks,
Miklos



Re: [PULL 00/17] doc updates and CentOS 7 removal

2021-06-02 Thread Peter Maydell
On Wed, 2 Jun 2021 at 08:36, Thomas Huth  wrote:
>
>  Hi Peter!
>
> The following changes since commit 52848929b70dcf92a68aedcfd90207be81ba3274:
>
>   Merge remote-tracking branch 
> 'remotes/kraxel/tags/usb-20210528-pull-request' into staging (2021-05-30 
> 20:10:30 +0100)
>
> are available in the Git repository at:
>
>   https://gitlab.com/thuth/qemu.git tags/pull-request-2021-06-02
>
> for you to fetch changes up to 2a85a08c998e418a46a308095893f223642f6fc9:
>
>   configure: bump min required CLang to 6.0 / XCode 10.0 (2021-06-02 09:11:32 
> +0200)
>
> 
> * Update the references to some doc files (use *.rst instead of *.txt)
> * Bump minimum versions of some requirements after removing CentOS 7 support
> 


Applied, thanks.

Please update the changelog at https://wiki.qemu.org/ChangeLog/6.1
for any user-visible changes.

-- PMM



Re: [PATCH 1/3] virtiofsd: Find original inode ID of mount points

2021-06-02 Thread Vivek Goyal
On Wed, May 12, 2021 at 02:55:42PM +0200, Max Reitz wrote:
> Mount point directories represent two inodes: On one hand, they are a
> normal directory on their parent filesystem.  On the other, they are the
> root node of the filesystem mounted there.  Thus, they have two inode
> IDs.
> 
> Right now, we only report the latter inode ID (i.e. the inode ID of the
> mounted filesystem's root node).  This is fine once the guest has
> auto-mounted a submount there (so this inode ID goes with a device ID
> that is distinct from the parent filesystem), but before the auto-mount,
> they have the device ID of the parent and the inode ID for the submount.
> This is problematic because this is likely exactly the same
> st_dev/st_ino combination as the parent filesystem's root node.  This
> leads to problems for example with `find`, which will thus complain
> about a filesystem loop if it has visited the parent filesystem's root
> node before, and then refuse to descend into the submount.
> 
> There is a way to find the mount directory's original inode ID, and that
> is to readdir(3) the parent directory, look for the mount directory, and
> read the dirent.d_ino field.  Using this, we can let lookup and
> readdirplus return that original inode ID, which the guest will thus
> show until the submount is auto-mounted.  (Then, it will invoke getattr
> and that stat(2) call will return the inode ID for the submount.)

[ CC miklos ]

Hi Max,

Though we discussed this in chat room, I am still responding to this
email with the concern I have, so that there is a record of it.

So with this patch for FUSE_LOOKUP  we always return submount's parentinode
id and with GETATTR request we return actual inode id of submount. That
kind of bothers me a bit as we are assuming that there is always going
to be a GETATTR request after FUSE_LOOKUP. FUSE_LOOKUP itself has attrs
returned with it and it might happen that after FUSE_LOOKUP, FUSE_GETATTR
might not be called at all because FUSE_LOOKUP itself got the latest
updated attrs with certain timeout.

For example, if I call stat on a normal file (not submount), I see that
after FUSE_LOOKUP, no FUSE_GETATTR request is going and
fuse_update_get_attr() is using attrs from locally cached inode attrs.

But same thing does not seem to be happening in case of submount. Once
submount is created in guest, I see that we never seem to be calling
->revalidate() on newly created dentry of submount root. I am not sure
why. And that means we don't do FUSE_LOOKUP and that means FUSE_GETATTR
always gets called.

I am not sure if this is a bug or expected behavior. I am not confident
that we can rely on this behavior of submount dentries. 

Ccing Miklos. He might have thoughts on this.

As we discussed, may be it is a better idea to create two inodes in
virtiofsd (like we do in guest). One for submount parent and one for
actual submount.

Thanks
Vivek


> 
> Signed-off-by: Max Reitz 
> ---
>  tools/virtiofsd/passthrough_ll.c | 104 +--
>  1 file changed, 99 insertions(+), 5 deletions(-)
> 
> diff --git a/tools/virtiofsd/passthrough_ll.c 
> b/tools/virtiofsd/passthrough_ll.c
> index 1553d2ef45..110b6e7e5b 100644
> --- a/tools/virtiofsd/passthrough_ll.c
> +++ b/tools/virtiofsd/passthrough_ll.c
> @@ -968,14 +968,87 @@ static int do_statx(struct lo_data *lo, int dirfd, 
> const char *pathname,
>  return 0;
>  }
>  
> +/*
> + * Use readdir() to find mp_name's inode ID on the parent's filesystem.
> + * (For mount points, stat() will only return the inode ID on the
> + * filesystem mounted there, i.e. the root directory's inode ID.  The
> + * mount point originally was a directory on the parent filesystem,
> + * though, and so has a different inode ID there.  When passing
> + * submount information to the guest, we need to pass this other ID,
> + * so the guest can use it as the inode ID until the submount is
> + * auto-mounted.  (At which point the guest will invoke getattr and
> + * find the inode ID on the submount.))
> + *
> + * Return 0 on success, and -errno otherwise.  *pino is set only in
> + * case of success.
> + */
> +static int get_mp_ino_on_parent(const struct lo_inode *dir, const char 
> *mp_name,
> +ino_t *pino)
> +{
> +int dirfd = -1;
> +int ret;
> +DIR *dp = NULL;
> +
> +dirfd = openat(dir->fd, ".", O_RDONLY);
> +if (dirfd < 0) {
> +ret = -errno;
> +goto out;
> +}
> +
> +dp = fdopendir(dirfd);
> +if (!dp) {
> +ret = -errno;
> +goto out;
> +}
> +/* Owned by dp now */
> +dirfd = -1;
> +
> +while (true) {
> +struct dirent *de;
> +
> +errno = 0;
> +de = readdir(dp);
> +if (!de) {
> +ret = errno ? -errno : -ENOENT;
> +goto out;
> +}
> +
> +if (!strcmp(de->d_name, mp_name)) {
> +*pino = de->d_ino;
> +ret = 0;
> +goto out;
> +}
> +}
> +
> +out:
> 

Re: [PATCH v8] qapi: introduce 'query-kvm-cpuid' action

2021-06-02 Thread Philippe Mathieu-Daudé
Hi Valeriy,

(Sorry for not looking earlier than v8)

On 5/31/21 2:38 PM, Valeriy Vdovin wrote:
> Introducing new qapi method 'query-kvm-cpuid'. This method can be used to
> get virtualized cpu model info generated by QEMU during VM initialization in
> the form of cpuid representation.
> 
> Diving into more details about virtual cpu generation: QEMU first parses 
> '-cpu'
> command line option. From there it takes the name of the model as the basis 
> for
> feature set of the new virtual cpu. After that it uses trailing '-cpu' 
> options,
> that state if additional cpu features should be present on the virtual cpu or
> excluded from it (tokens '+'/'-' or '=on'/'=off').
> After that QEMU checks if the host's cpu can actually support the derived
> feature set and applies host limitations to it.
> After this initialization procedure, virtual cpu has it's model and
> vendor names, and a working feature set and is ready for identification
> instructions such as CPUID.
> 
> Currently full output for this method is only supported for x86 cpus.
> 
> To learn exactly how virtual cpu is presented to the guest machine via CPUID
> instruction, new qapi method can be used. By calling 'query-kvm-cpuid'
> method, one can get a full listing of all CPUID leafs with subleafs which are
> supported by the initialized virtual cpu.
> 
> Other than debug, the method is useful in cases when we would like to
> utilize QEMU's virtual cpu initialization routines and put the retrieved
> values into kernel CPUID overriding mechanics for more precise control
> over how various processes perceive its underlying hardware with
> container processes as a good example.
> 
> Output format:
> The output is a plain list of leaf/subleaf agrument combinations, that
> return 4 words in registers EAX, EBX, ECX, EDX.
> 
> Use example:
> qmp_request: {
>   "execute": "query-kvm-cpuid"
> }
> 
> qmp_response: [
>   {
> "eax": 1073741825,
> "edx": 77,
> "in_eax": 1073741824,
> "ecx": 1447775574,
> "ebx": 1263359563,
>   },
>   {
> "eax": 16777339,
> "edx": 0,
> "in_eax": 1073741825,
> "ecx": 0,
> "ebx": 0,
>   },
>   {
> "eax": 13,
> "edx": 1231384169,
> "in_eax": 0,
> "ecx": 1818588270,
> "ebx": 1970169159,
>   },
>   {
> "eax": 198354,
> "edx": 126614527,
>   
> 
> Signed-off-by: Valeriy Vdovin 

---

> 
> v2: - Removed leaf/subleaf iterators.
> - Modified cpu_x86_cpuid to return false in cases when count is
>   greater than supported subleaves.
> v3: - Fixed structure name coding style.
> - Added more comments
> - Ensured buildability for non-x86 targets.
> v4: - Fixed cpu_x86_cpuid return value logic and handling of 0xA leaf.
> - Fixed comments.
> - Removed target check in qmp_query_cpu_model_cpuid.
> v5: - Added error handling code in qmp_query_cpu_model_cpuid
> v6: - Fixed error handling code. Added method to query_error_class
> v7: - Changed implementation in favor of cached cpuid_data for
>   KVM_SET_CPUID2
> v8: - Renamed qmp method to query-kvm-cpuid and some fields in response.
> - Modified documentation to qmp method
> - Removed helper struct declaration
> ---

^ Below this '---' go your comments.

>  qapi/machine-target.json   | 43 ++
>  target/i386/kvm/kvm.c  | 37 
>  tests/qtest/qmp-cmd-test.c |  1 +
>  3 files changed, 81 insertions(+)
> 
> diff --git a/qapi/machine-target.json b/qapi/machine-target.json
> index e7811654b7..a83180dd24 100644
> --- a/qapi/machine-target.json
> +++ b/qapi/machine-target.json
> @@ -329,3 +329,46 @@
>  ##
>  { 'command': 'query-cpu-definitions', 'returns': ['CpuDefinitionInfo'],
>'if': 'defined(TARGET_PPC) || defined(TARGET_ARM) || defined(TARGET_I386) 
> || defined(TARGET_S390X) || defined(TARGET_MIPS)' }
> +
> +##
> +# @CpuidEntry:
> +#
> +# A single entry of a CPUID response.
> +#
> +# One entry holds full set of information (leaf) returned to the guest in 
> response
> +# to it calling a CPUID instruction with eax, ecx used as the agruments to 
> that
> +# instruction. ecx is an optional argument as not all of the leaves support 
> it.
> +#
> +# @in_eax: CPUID argument in eax
> +# @in_ecx: CPUID argument in ecx
> +# @eax: eax
> +# @ebx: ebx
> +# @ecx: ecx
> +# @edx: edx
> +#
> +# Since: 6.1
> +##
> +{ 'struct': 'CpuidEntry',
> +  'data': { 'in_eax' : 'uint32',
> +'*in_ecx' : 'uint32',
> +'eax' : 'uint32',
> +'ebx' : 'uint32',
> +'ecx' : 'uint32',
> +'edx' : 'uint32'
> +  },
> +  'if': 'defined(TARGET_I386) && defined(CONFIG_KVM)' }

What about other accelerators?

> +
> +##
> +# @query-kvm-cpuid:
> +#
> +# Returns raw data from the KVM CPUID table for the first VCPU.
> +# The KVM CPUID table defines the response to the CPUID
> +# instruction when executed by the guest operating system.

What is specific to KVM here?

What about 'query-accel-cpuid' or 

[PATCH v4 8/8] hw/arm/virt: add ITS support in virt GIC

2021-06-02 Thread Shashi Mallela
Included creation of ITS as part of virt platform GIC
initialization.This Emulated ITS model now co-exists with kvm
ITS and is enabled in absence of kvm irq kernel support in a
platform.

Signed-off-by: Shashi Mallela 
---
 hw/arm/virt.c | 27 +--
 include/hw/arm/virt.h |  2 ++
 target/arm/kvm_arm.h  |  4 ++--
 3 files changed, 29 insertions(+), 4 deletions(-)

diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index 840758666d..f598f048da 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -583,6 +583,12 @@ static void create_its(VirtMachineState *vms)
 const char *itsclass = its_class_name();
 DeviceState *dev;
 
+if (!strcmp(itsclass, "arm-gicv3-its")) {
+if (!vms->tcg_its) {
+itsclass = NULL;
+}
+}
+
 if (!itsclass) {
 /* Do nothing if not supported */
 return;
@@ -620,7 +626,7 @@ static void create_v2m(VirtMachineState *vms)
 vms->msi_controller = VIRT_MSI_CTRL_GICV2M;
 }
 
-static void create_gic(VirtMachineState *vms)
+static void create_gic(VirtMachineState *vms, MemoryRegion *mem)
 {
 MachineState *ms = MACHINE(vms);
 /* We create a standalone GIC */
@@ -654,6 +660,14 @@ static void create_gic(VirtMachineState *vms)
  nb_redist_regions);
 qdev_prop_set_uint32(vms->gic, "redist-region-count[0]", 
redist0_count);
 
+if (!kvm_irqchip_in_kernel()) {
+if (vms->tcg_its) {
+object_property_set_link(OBJECT(vms->gic), "sysmem",
+ OBJECT(mem), _fatal);
+qdev_prop_set_bit(vms->gic, "has-lpi", true);
+}
+}
+
 if (nb_redist_regions == 2) {
 uint32_t redist1_capacity =
 vms->memmap[VIRT_HIGH_GIC_REDIST2].size / 
GICV3_REDIST_SIZE;
@@ -2039,7 +2053,7 @@ static void machvirt_init(MachineState *machine)
 
 virt_flash_fdt(vms, sysmem, secure_sysmem ?: sysmem);
 
-create_gic(vms);
+create_gic(vms, sysmem);
 
 virt_cpu_post_init(vms, sysmem);
 
@@ -2718,6 +2732,12 @@ static void virt_instance_init(Object *obj)
 } else {
 /* Default allows ITS instantiation */
 vms->its = true;
+
+if (vmc->no_tcg_its) {
+vms->tcg_its = false;
+} else {
+vms->tcg_its = true;
+}
 }
 
 /* Default disallows iommu instantiation */
@@ -2764,6 +2784,9 @@ DEFINE_VIRT_MACHINE_AS_LATEST(6, 1)
 
 static void virt_machine_6_0_options(MachineClass *mc)
 {
+VirtMachineClass *vmc = VIRT_MACHINE_CLASS(OBJECT_CLASS(mc));
+/* qemu ITS was introduced with 6.1 */
+vmc->no_tcg_its = true;
 }
 DEFINE_VIRT_MACHINE(6, 0)
 
diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h
index 921416f918..f873ab9068 100644
--- a/include/hw/arm/virt.h
+++ b/include/hw/arm/virt.h
@@ -120,6 +120,7 @@ struct VirtMachineClass {
 MachineClass parent;
 bool disallow_affinity_adjustment;
 bool no_its;
+bool no_tcg_its;
 bool no_pmu;
 bool claim_edge_triggered_timers;
 bool smbios_old_sys_ver;
@@ -141,6 +142,7 @@ struct VirtMachineState {
 bool highmem;
 bool highmem_ecam;
 bool its;
+bool tcg_its;
 bool virt;
 bool ras;
 bool mte;
diff --git a/target/arm/kvm_arm.h b/target/arm/kvm_arm.h
index 34f8daa377..0613454975 100644
--- a/target/arm/kvm_arm.h
+++ b/target/arm/kvm_arm.h
@@ -525,8 +525,8 @@ static inline const char *its_class_name(void)
 /* KVM implementation requires this capability */
 return kvm_direct_msi_enabled() ? "arm-its-kvm" : NULL;
 } else {
-/* Software emulation is not implemented yet */
-return NULL;
+/* Software emulation based model */
+return "arm-gicv3-its";
 }
 }
 
-- 
2.27.0




Re: [PATCH v7 23/27] tcg/tci: Split out tci_qemu_ld, tci_qemu_st

2021-06-02 Thread Philippe Mathieu-Daudé
On 6/1/21 5:01 PM, Richard Henderson wrote:
> We can share this code between 32-bit and 64-bit loads and stores.
> 
> Signed-off-by: Richard Henderson 
> ---
>  tcg/tci.c | 183 +-
>  1 file changed, 71 insertions(+), 112 deletions(-)

Reviewed-by: Philippe Mathieu-Daudé 



[PATCH v4 7/8] hw/arm/sbsa-ref: add ITS support in SBSA GIC

2021-06-02 Thread Shashi Mallela
Included creation of ITS as part of SBSA platform GIC
initialization.

Signed-off-by: Shashi Mallela 
---
 hw/arm/sbsa-ref.c | 26 +++---
 1 file changed, 23 insertions(+), 3 deletions(-)

diff --git a/hw/arm/sbsa-ref.c b/hw/arm/sbsa-ref.c
index 43c19b4923..3d9c073636 100644
--- a/hw/arm/sbsa-ref.c
+++ b/hw/arm/sbsa-ref.c
@@ -34,7 +34,7 @@
 #include "hw/boards.h"
 #include "hw/ide/internal.h"
 #include "hw/ide/ahci_internal.h"
-#include "hw/intc/arm_gicv3_common.h"
+#include "hw/intc/arm_gicv3_its_common.h"
 #include "hw/loader.h"
 #include "hw/pci-host/gpex.h"
 #include "hw/qdev-properties.h"
@@ -64,6 +64,7 @@ enum {
 SBSA_CPUPERIPHS,
 SBSA_GIC_DIST,
 SBSA_GIC_REDIST,
+SBSA_GIC_ITS,
 SBSA_SECURE_EC,
 SBSA_GWDT,
 SBSA_GWDT_REFRESH,
@@ -107,6 +108,7 @@ static const MemMapEntry sbsa_ref_memmap[] = {
 [SBSA_CPUPERIPHS] = { 0x4000, 0x0004 },
 [SBSA_GIC_DIST] =   { 0x4006, 0x0001 },
 [SBSA_GIC_REDIST] = { 0x4008, 0x0400 },
+[SBSA_GIC_ITS] ={ 0x4409, 0x0002 },
 [SBSA_SECURE_EC] =  { 0x5000, 0x1000 },
 [SBSA_GWDT_REFRESH] =   { 0x5001, 0x1000 },
 [SBSA_GWDT_CONTROL] =   { 0x50011000, 0x1000 },
@@ -377,7 +379,20 @@ static void create_secure_ram(SBSAMachineState *sms,
 memory_region_add_subregion(secure_sysmem, base, secram);
 }
 
-static void create_gic(SBSAMachineState *sms)
+static void create_its(SBSAMachineState *sms)
+{
+DeviceState *dev;
+
+dev = qdev_new(TYPE_ARM_GICV3_ITS);
+SysBusDevice *s = SYS_BUS_DEVICE(dev);
+
+object_property_set_link(OBJECT(dev), "parent-gicv3", OBJECT(sms->gic),
+ _abort);
+sysbus_realize_and_unref(s, _fatal);
+sysbus_mmio_map(s, 0, sbsa_ref_memmap[SBSA_GIC_ITS].base);
+}
+
+static void create_gic(SBSAMachineState *sms, MemoryRegion *mem)
 {
 unsigned int smp_cpus = MACHINE(sms)->smp.cpus;
 SysBusDevice *gicbusdev;
@@ -404,6 +419,10 @@ static void create_gic(SBSAMachineState *sms)
 qdev_prop_set_uint32(sms->gic, "len-redist-region-count", 1);
 qdev_prop_set_uint32(sms->gic, "redist-region-count[0]", redist0_count);
 
+object_property_set_link(OBJECT(sms->gic), "sysmem", OBJECT(mem),
+ _fatal);
+qdev_prop_set_bit(sms->gic, "has-lpi", true);
+
 gicbusdev = SYS_BUS_DEVICE(sms->gic);
 sysbus_realize_and_unref(gicbusdev, _fatal);
 sysbus_mmio_map(gicbusdev, 0, sbsa_ref_memmap[SBSA_GIC_DIST].base);
@@ -450,6 +469,7 @@ static void create_gic(SBSAMachineState *sms)
 sysbus_connect_irq(gicbusdev, i + 3 * smp_cpus,
qdev_get_gpio_in(cpudev, ARM_CPU_VFIQ));
 }
+create_its(sms);
 }
 
 static void create_uart(const SBSAMachineState *sms, int uart,
@@ -762,7 +782,7 @@ static void sbsa_ref_init(MachineState *machine)
 
 create_secure_ram(sms, secure_sysmem);
 
-create_gic(sms);
+create_gic(sms, sysmem);
 
 create_uart(sms, SBSA_UART, sysmem, serial_hd(0));
 create_uart(sms, SBSA_SECURE_UART, secure_sysmem, serial_hd(1));
-- 
2.27.0




[PATCH v4 6/8] hw/intc: GICv3 redistributor ITS processing

2021-06-02 Thread Shashi Mallela
Implemented lpi processing at redistributor to get lpi config info
from lpi configuration table,determine priority,set pending state in
lpi pending table and forward the lpi to cpuif.Added logic to invoke
redistributor lpi processing with translated LPI which set/clear LPI
from ITS device as part of ITS INT,CLEAR,DISCARD command and
GITS_TRANSLATER processing.

Signed-off-by: Shashi Mallela 
---
 hw/intc/arm_gicv3.c|   9 ++
 hw/intc/arm_gicv3_common.c |   1 +
 hw/intc/arm_gicv3_cpuif.c  |   7 +-
 hw/intc/arm_gicv3_its.c|  14 ++-
 hw/intc/arm_gicv3_redist.c | 145 +
 hw/intc/gicv3_internal.h   |  10 ++
 include/hw/intc/arm_gicv3_common.h |  10 ++
 7 files changed, 190 insertions(+), 6 deletions(-)

diff --git a/hw/intc/arm_gicv3.c b/hw/intc/arm_gicv3.c
index d63f8af604..4d19190b9c 100644
--- a/hw/intc/arm_gicv3.c
+++ b/hw/intc/arm_gicv3.c
@@ -165,6 +165,15 @@ static void gicv3_redist_update_noirqset(GICv3CPUState *cs)
 cs->hppi.grp = gicv3_irq_group(cs->gic, cs, cs->hppi.irq);
 }
 
+if (cs->gic->lpi_enable && cs->lpivalid) {
+if (irqbetter(cs, cs->hpplpi.irq, cs->hpplpi.prio)) {
+cs->hppi.irq = cs->hpplpi.irq;
+cs->hppi.prio = cs->hpplpi.prio;
+cs->hppi.grp = cs->hpplpi.grp;
+seenbetter = true;
+}
+}
+
 /* If the best interrupt we just found would preempt whatever
  * was the previous best interrupt before this update, then
  * we know it's definitely the best one now.
diff --git a/hw/intc/arm_gicv3_common.c b/hw/intc/arm_gicv3_common.c
index 53dea2a775..223db16fec 100644
--- a/hw/intc/arm_gicv3_common.c
+++ b/hw/intc/arm_gicv3_common.c
@@ -435,6 +435,7 @@ static void arm_gicv3_common_reset(DeviceState *dev)
 memset(cs->gicr_ipriorityr, 0, sizeof(cs->gicr_ipriorityr));
 
 cs->hppi.prio = 0xff;
+cs->hpplpi.prio = 0xff;
 
 /* State in the CPU interface must *not* be reset here, because it
  * is part of the CPU's reset domain, not the GIC device's.
diff --git a/hw/intc/arm_gicv3_cpuif.c b/hw/intc/arm_gicv3_cpuif.c
index 81f94c7f4a..5be3efaa3f 100644
--- a/hw/intc/arm_gicv3_cpuif.c
+++ b/hw/intc/arm_gicv3_cpuif.c
@@ -898,10 +898,12 @@ static void icc_activate_irq(GICv3CPUState *cs, int irq)
 cs->gicr_iactiver0 = deposit32(cs->gicr_iactiver0, irq, 1, 1);
 cs->gicr_ipendr0 = deposit32(cs->gicr_ipendr0, irq, 1, 0);
 gicv3_redist_update(cs);
-} else {
+} else if (irq < GICV3_LPI_INTID_START) {
 gicv3_gicd_active_set(cs->gic, irq);
 gicv3_gicd_pending_clear(cs->gic, irq);
 gicv3_update(cs->gic, irq, 1);
+} else {
+gicv3_redist_lpi_pending(cs, irq, 0);
 }
 }
 
@@ -1317,7 +1319,8 @@ static void icc_eoir_write(CPUARMState *env, const 
ARMCPRegInfo *ri,
 trace_gicv3_icc_eoir_write(is_eoir0 ? 0 : 1,
gicv3_redist_affid(cs), value);
 
-if (irq >= cs->gic->num_irq) {
+if ((irq >= cs->gic->num_irq) &&  (!(cs->gic->lpi_enable &&
+(irq >= GICV3_LPI_INTID_START {
 /* This handles two cases:
  * 1. If software writes the ID of a spurious interrupt [ie 1020-1023]
  * to the GICC_EOIR, the GIC ignores that write.
diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c
index 0a978cf55b..e0fbd4041f 100644
--- a/hw/intc/arm_gicv3_its.c
+++ b/hw/intc/arm_gicv3_its.c
@@ -211,6 +211,7 @@ static MemTxResult process_int(GICv3ITSState *s, uint64_t 
value,
 bool ite_valid = false;
 uint64_t cte = 0;
 bool cte_valid = false;
+uint64_t rdbase;
 uint64_t itel = 0;
 uint32_t iteh = 0;
 
@@ -267,10 +268,15 @@ static MemTxResult process_int(GICv3ITSState *s, uint64_t 
value,
  * command in the queue
  */
 } else {
-/*
- * Current implementation only supports rdbase == procnum
- * Hence rdbase physical address is ignored
- */
+rdbase = (cte >> 1U) & RDBASE_PROCNUM_MASK;
+assert(rdbase <= s->gicv3->num_cpu);
+
+if ((cmd == CLEAR) || (cmd == DISCARD)) {
+gicv3_redist_process_lpi(>gicv3->cpu[rdbase], pIntid, 0);
+} else {
+gicv3_redist_process_lpi(>gicv3->cpu[rdbase], pIntid, 1);
+}
+
 if (cmd == DISCARD) {
 /* remove mapping from interrupt translation table */
 res = update_ite(s, eventid, dte, itel, iteh);
diff --git a/hw/intc/arm_gicv3_redist.c b/hw/intc/arm_gicv3_redist.c
index fb9a4ee3cc..bfc6e4e9b9 100644
--- a/hw/intc/arm_gicv3_redist.c
+++ b/hw/intc/arm_gicv3_redist.c
@@ -255,6 +255,11 @@ static MemTxResult gicr_writel(GICv3CPUState *cs, hwaddr 
offset,
 if (cs->gicr_typer & GICR_TYPER_PLPIS) {
 if (value & GICR_CTLR_ENABLE_LPIS) {
 cs->gicr_ctlr |= GICR_CTLR_ENABLE_LPIS;
+/* Check for any pending interr in pending table */
+

[PATCH v4 5/8] hw/intc: GICv3 ITS Feature enablement

2021-06-02 Thread Shashi Mallela
Added properties to enable ITS feature and define qemu system
address space memory in gicv3 common,setup distributor and
redistributor registers to indicate LPI support.

Signed-off-by: Shashi Mallela 
---
 hw/intc/arm_gicv3_common.c | 12 
 hw/intc/arm_gicv3_dist.c   |  7 +--
 hw/intc/arm_gicv3_its.c|  9 -
 hw/intc/arm_gicv3_redist.c | 14 +++---
 hw/intc/gicv3_internal.h   | 17 +
 include/hw/intc/arm_gicv3_common.h |  1 +
 6 files changed, 54 insertions(+), 6 deletions(-)

diff --git a/hw/intc/arm_gicv3_common.c b/hw/intc/arm_gicv3_common.c
index 58ef65f589..53dea2a775 100644
--- a/hw/intc/arm_gicv3_common.c
+++ b/hw/intc/arm_gicv3_common.c
@@ -345,6 +345,11 @@ static void arm_gicv3_common_realize(DeviceState *dev, 
Error **errp)
 return;
 }
 
+if (s->lpi_enable && !s->dma) {
+error_setg(errp, "Redist-ITS: Guest 'sysmem' reference link not set");
+return;
+}
+
 s->cpu = g_new0(GICv3CPUState, s->num_cpu);
 
 for (i = 0; i < s->num_cpu; i++) {
@@ -381,6 +386,10 @@ static void arm_gicv3_common_realize(DeviceState *dev, 
Error **errp)
 (1 << 24) |
 (i << 8) |
 (last << 4);
+
+if (s->lpi_enable) {
+s->cpu[i].gicr_typer |= GICR_TYPER_PLPIS;
+}
 }
 }
 
@@ -494,9 +503,12 @@ static Property arm_gicv3_common_properties[] = {
 DEFINE_PROP_UINT32("num-cpu", GICv3State, num_cpu, 1),
 DEFINE_PROP_UINT32("num-irq", GICv3State, num_irq, 32),
 DEFINE_PROP_UINT32("revision", GICv3State, revision, 3),
+DEFINE_PROP_BOOL("has-lpi", GICv3State, lpi_enable, 0),
 DEFINE_PROP_BOOL("has-security-extensions", GICv3State, security_extn, 0),
 DEFINE_PROP_ARRAY("redist-region-count", GICv3State, nb_redist_regions,
   redist_region_count, qdev_prop_uint32, uint32_t),
+DEFINE_PROP_LINK("sysmem", GICv3State, dma, TYPE_MEMORY_REGION,
+ MemoryRegion *),
 DEFINE_PROP_END_OF_LIST(),
 };
 
diff --git a/hw/intc/arm_gicv3_dist.c b/hw/intc/arm_gicv3_dist.c
index b65f56f903..7e57654061 100644
--- a/hw/intc/arm_gicv3_dist.c
+++ b/hw/intc/arm_gicv3_dist.c
@@ -371,7 +371,9 @@ static MemTxResult gicd_readl(GICv3State *s, hwaddr offset,
  * A3V == 1 (non-zero values of Affinity level 3 supported)
  * IDbits == 0xf (we support 16-bit interrupt identifiers)
  * DVIS == 0 (Direct virtual LPI injection not supported)
- * LPIS == 0 (LPIs not supported)
+ * LPIS == 1 (LPIs are supported if affinity routing is enabled)
+ * num_LPIs == 0b0 (bits [15:11],Number of LPIs as indicated
+ *  by GICD_TYPER.IDbits)
  * MBIS == 0 (message-based SPIs not supported)
  * SecurityExtn == 1 if security extns supported
  * CPUNumber == 0 since for us ARE is always 1
@@ -386,7 +388,8 @@ static MemTxResult gicd_readl(GICv3State *s, hwaddr offset,
 bool sec_extn = !(s->gicd_ctlr & GICD_CTLR_DS);
 
 *data = (1 << 25) | (1 << 24) | (sec_extn << 10) |
-(0xf << 19) | itlinesnumber;
+(s->lpi_enable << GICD_TYPER_LPIS_OFFSET) |
+(GICD_TYPER_IDBITS << GICD_TYPER_IDBITS_OFFSET) | itlinesnumber;
 return MEMTX_OK;
 }
 case GICD_IIDR:
diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c
index 82bb5b84ef..0a978cf55b 100644
--- a/hw/intc/arm_gicv3_its.c
+++ b/hw/intc/arm_gicv3_its.c
@@ -294,6 +294,7 @@ static MemTxResult process_mapti(GICv3ITSState *s, uint64_t 
value,
 uint64_t itel = 0;
 uint32_t iteh = 0;
 uint32_t int_spurious = INTID_SPURIOUS;
+uint64_t idbits;
 
 devid = (value >> DEVID_SHIFT) & DEVID_MASK;
 offset += NUM_BYTES_IN_DW;
@@ -330,7 +331,13 @@ static MemTxResult process_mapti(GICv3ITSState *s, 
uint64_t value,
 max_eventid = (1UL << (((dte >> 1U) & SIZE_MASK) + 1));
 
 if (!ignore_pInt) {
-max_Intid = (1UL << (FIELD_EX64(s->typer, GITS_TYPER, IDBITS) + 1));
+idbits = MIN(FIELD_EX64(s->gicv3->cpu->gicr_propbaser, GICR_PROPBASER,
+IDBITS), GICD_TYPER_IDBITS);
+
+if (idbits < GICR_PROPBASER_IDBITS_THRESHOLD) {
+return res;
+}
+max_Intid = (1ULL << (idbits + 1));
 }
 
 if ((devid > s->dt.max_devids) || (icid > s->ct.max_collids) ||
diff --git a/hw/intc/arm_gicv3_redist.c b/hw/intc/arm_gicv3_redist.c
index 8645220d61..fb9a4ee3cc 100644
--- a/hw/intc/arm_gicv3_redist.c
+++ b/hw/intc/arm_gicv3_redist.c
@@ -244,14 +244,21 @@ static MemTxResult gicr_readl(GICv3CPUState *cs, hwaddr 
offset,
 static MemTxResult gicr_writel(GICv3CPUState *cs, hwaddr offset,
uint64_t value, MemTxAttrs attrs)
 {
+
 switch (offset) {
 case GICR_CTLR:
 /* For our implementation, GICR_TYPER.DPGS is 0 and so all
  * the DPG bits are RAZ/WI. We don't do anything asynchronously,
-   

Re: [PATCH v7 25/27] tcg/tci: Remove the qemu_ld/st_type macros

2021-06-02 Thread Philippe Mathieu-Daudé
On 6/1/21 5:01 PM, Richard Henderson wrote:
> These macros are only used in one place.  By expanding,
> we get to apply some common-subexpression elimination
> and create some local variables.
> 
> Signed-off-by: Richard Henderson 
> ---
>  tcg/tci.c | 165 +-
>  1 file changed, 100 insertions(+), 65 deletions(-)

Reviewed-by: Philippe Mathieu-Daudé 



[PATCH v4 4/8] hw/intc: GICv3 ITS Command processing

2021-06-02 Thread Shashi Mallela
Added ITS command queue handling for MAPTI,MAPI commands,handled ITS
translation which triggers an LPI via INT command as well as write
to GITS_TRANSLATER register,defined enum to differentiate between ITS
command interrupt trigger and GITS_TRANSLATER based interrupt trigger.
Each of these commands make use of other functionalities implemented to
get device table entry,collection table entry or interrupt translation
table entry required for their processing.

Signed-off-by: Shashi Mallela 
---
 hw/intc/arm_gicv3_its.c| 334 +
 hw/intc/gicv3_internal.h   |  12 ++
 include/hw/intc/arm_gicv3_common.h |   2 +
 3 files changed, 348 insertions(+)

diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c
index 6551c577b3..82bb5b84ef 100644
--- a/hw/intc/arm_gicv3_its.c
+++ b/hw/intc/arm_gicv3_its.c
@@ -28,6 +28,13 @@ struct GICv3ITSClass {
 void (*parent_reset)(DeviceState *dev);
 };
 
+typedef enum ItsCmdType {
+NONE = 0, /* internal indication for GITS_TRANSLATER write */
+CLEAR = 1,
+DISCARD = 2,
+INT = 3,
+} ItsCmdType;
+
 static uint64_t baser_base_addr(uint64_t value, uint32_t page_sz)
 {
 uint64_t result = 0;
@@ -49,6 +56,315 @@ static uint64_t baser_base_addr(uint64_t value, uint32_t 
page_sz)
 return result;
 }
 
+static bool get_cte(GICv3ITSState *s, uint16_t icid, uint64_t *cte,
+MemTxResult *res)
+{
+AddressSpace *as = >gicv3->dma_as;
+uint64_t l2t_addr;
+uint64_t value;
+bool valid_l2t;
+uint32_t l2t_id;
+uint32_t max_l2_entries;
+bool status = false;
+
+if (s->ct.indirect) {
+l2t_id = icid / (s->ct.page_sz / L1TABLE_ENTRY_SIZE);
+
+value = address_space_ldq_le(as,
+ s->ct.base_addr +
+ (l2t_id * L1TABLE_ENTRY_SIZE),
+ MEMTXATTRS_UNSPECIFIED, res);
+
+if (*res == MEMTX_OK) {
+valid_l2t = (value >> VALID_SHIFT) & VALID_MASK;
+
+if (valid_l2t) {
+max_l2_entries = s->ct.page_sz / s->ct.entry_sz;
+
+l2t_addr = value & ((1ULL << 51) - 1);
+
+*cte =  address_space_ldq_le(as, l2t_addr +
+((icid % max_l2_entries) * GITS_CTE_SIZE),
+MEMTXATTRS_UNSPECIFIED, res);
+   }
+   }
+} else {
+/* Flat level table */
+*cte =  address_space_ldq_le(as, s->ct.base_addr +
+ (icid * GITS_CTE_SIZE),
+  MEMTXATTRS_UNSPECIFIED, res);
+}
+
+if (*cte & VALID_MASK) {
+status = true;
+}
+
+return status;
+}
+
+static MemTxResult update_ite(GICv3ITSState *s, uint32_t eventid, uint64_t dte,
+  uint64_t itel, uint32_t iteh)
+{
+AddressSpace *as = >gicv3->dma_as;
+uint64_t itt_addr;
+MemTxResult res = MEMTX_OK;
+
+itt_addr = (dte >> 6ULL) & ITTADDR_MASK;
+itt_addr <<= ITTADDR_SHIFT; /* 256 byte aligned */
+
+address_space_stq_le(as, itt_addr + (eventid * sizeof(uint64_t)),
+ itel, MEMTXATTRS_UNSPECIFIED, );
+
+if (res == MEMTX_OK) {
+address_space_stl_le(as, itt_addr + ((eventid + sizeof(uint64_t)) *
+ sizeof(uint32_t)), iteh, MEMTXATTRS_UNSPECIFIED,
+ );
+}
+   return res;
+}
+
+static bool get_ite(GICv3ITSState *s, uint32_t eventid, uint64_t dte,
+uint16_t *icid, uint32_t *pIntid, MemTxResult *res)
+{
+AddressSpace *as = >gicv3->dma_as;
+uint64_t itt_addr;
+bool status = false;
+uint64_t itel = 0;
+uint32_t iteh = 0;
+
+itt_addr = (dte >> 6ULL) & ITTADDR_MASK;
+itt_addr <<= ITTADDR_SHIFT; /* 256 byte aligned */
+
+itel = address_space_ldq_le(as, itt_addr + (eventid * sizeof(uint64_t)),
+MEMTXATTRS_UNSPECIFIED, res);
+
+if (*res == MEMTX_OK) {
+iteh = address_space_ldl_le(as, itt_addr + ((eventid +
+sizeof(uint64_t)) * sizeof(uint32_t)),
+MEMTXATTRS_UNSPECIFIED, res);
+
+if (*res == MEMTX_OK) {
+if (itel & VALID_MASK) {
+if ((itel >> ITE_ENTRY_INTTYPE_SHIFT) & GITS_TYPE_PHYSICAL) {
+*pIntid = (itel >> ITE_ENTRY_INTID_SHIFT) &
+   ITE_ENTRY_INTID_MASK;
+*icid = iteh & ITE_ENTRY_ICID_MASK;
+status = true;
+}
+}
+}
+}
+return status;
+}
+
+static uint64_t get_dte(GICv3ITSState *s, uint32_t devid, MemTxResult *res)
+{
+AddressSpace *as = >gicv3->dma_as;
+uint64_t l2t_addr;
+uint64_t value;
+bool valid_l2t;
+uint32_t l2t_id;
+uint32_t max_l2_entries;
+
+if (s->dt.indirect) {
+l2t_id = devid / 

[PATCH v4 3/8] hw/intc: GICv3 ITS command queue framework

2021-06-02 Thread Shashi Mallela
Added functionality to trigger ITS command queue processing on
write to CWRITE register and process each command queue entry to
identify the command type and handle commands like MAPD,MAPC,SYNC.

Signed-off-by: Shashi Mallela 
---
 hw/intc/arm_gicv3_its.c  | 295 +++
 hw/intc/gicv3_internal.h |  37 +
 2 files changed, 332 insertions(+)

diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c
index af60f19c98..6551c577b3 100644
--- a/hw/intc/arm_gicv3_its.c
+++ b/hw/intc/arm_gicv3_its.c
@@ -49,6 +49,295 @@ static uint64_t baser_base_addr(uint64_t value, uint32_t 
page_sz)
 return result;
 }
 
+static MemTxResult update_cte(GICv3ITSState *s, uint16_t icid, bool valid,
+  uint64_t rdbase)
+{
+AddressSpace *as = >gicv3->dma_as;
+uint64_t value;
+uint64_t l2t_addr;
+bool valid_l2t;
+uint32_t l2t_id;
+uint32_t max_l2_entries;
+uint64_t cte = 0;
+MemTxResult res = MEMTX_OK;
+
+if (!s->ct.valid) {
+return res;
+}
+
+if (valid) {
+/* add mapping entry to collection table */
+cte = (valid & VALID_MASK) |
+  ((rdbase & RDBASE_PROCNUM_MASK) << 1ULL);
+}
+
+/*
+ * The specification defines the format of level 1 entries of a
+ * 2-level table, but the format of level 2 entries and the format
+ * of flat-mapped tables is IMPDEF.
+ */
+if (s->ct.indirect) {
+l2t_id = icid / (s->ct.page_sz / L1TABLE_ENTRY_SIZE);
+
+value = address_space_ldq_le(as,
+ s->ct.base_addr +
+ (l2t_id * L1TABLE_ENTRY_SIZE),
+ MEMTXATTRS_UNSPECIFIED, );
+
+if (res != MEMTX_OK) {
+return res;
+}
+
+valid_l2t = (value >> VALID_SHIFT) & VALID_MASK;
+
+if (valid_l2t) {
+max_l2_entries = s->ct.page_sz / s->ct.entry_sz;
+
+l2t_addr = value & ((1ULL << 51) - 1);
+
+address_space_stq_le(as, l2t_addr +
+ ((icid % max_l2_entries) * GITS_CTE_SIZE),
+ cte, MEMTXATTRS_UNSPECIFIED, );
+}
+} else {
+/* Flat level table */
+address_space_stq_le(as, s->ct.base_addr + (icid * GITS_CTE_SIZE),
+ cte, MEMTXATTRS_UNSPECIFIED, );
+}
+return res;
+}
+
+static MemTxResult process_mapc(GICv3ITSState *s, uint32_t offset)
+{
+AddressSpace *as = >gicv3->dma_as;
+uint16_t icid;
+uint64_t rdbase;
+bool valid;
+MemTxResult res = MEMTX_OK;
+uint64_t value;
+
+offset += NUM_BYTES_IN_DW;
+offset += NUM_BYTES_IN_DW;
+
+value = address_space_ldq_le(as, s->cq.base_addr + offset,
+ MEMTXATTRS_UNSPECIFIED, );
+
+if (res != MEMTX_OK) {
+return res;
+}
+
+icid = value & ICID_MASK;
+
+rdbase = (value >> R_MAPC_RDBASE_SHIFT) & RDBASE_PROCNUM_MASK;
+
+valid = (value >> VALID_SHIFT) & VALID_MASK;
+
+if ((icid > s->ct.max_collids) || (rdbase > s->gicv3->num_cpu)) {
+qemu_log_mask(LOG_GUEST_ERROR,
+  "ITS MAPC: invalid collection table attributes "
+  "icid %d rdbase %lu\n",  icid, rdbase);
+/*
+ * in this implementation,in case of error
+ * we ignore this command and move onto the next
+ * command in the queue
+ */
+} else {
+res = update_cte(s, icid, valid, rdbase);
+}
+
+return res;
+}
+
+static MemTxResult update_dte(GICv3ITSState *s, uint32_t devid, bool valid,
+  uint8_t size, uint64_t itt_addr)
+{
+AddressSpace *as = >gicv3->dma_as;
+uint64_t value;
+uint64_t l2t_addr;
+bool valid_l2t;
+uint32_t l2t_id;
+uint32_t max_l2_entries;
+uint64_t dte = 0;
+MemTxResult res = MEMTX_OK;
+
+if (s->dt.valid) {
+if (valid) {
+/* add mapping entry to device table */
+dte = (valid & VALID_MASK) |
+  ((size & SIZE_MASK) << 1U) |
+  ((itt_addr & ITTADDR_MASK) << 6ULL);
+}
+} else {
+return res;
+}
+
+/*
+ * The specification defines the format of level 1 entries of a
+ * 2-level table, but the format of level 2 entries and the format
+ * of flat-mapped tables is IMPDEF.
+ */
+if (s->dt.indirect) {
+l2t_id = devid / (s->dt.page_sz / L1TABLE_ENTRY_SIZE);
+
+value = address_space_ldq_le(as,
+ s->dt.base_addr +
+ (l2t_id * L1TABLE_ENTRY_SIZE),
+ MEMTXATTRS_UNSPECIFIED, );
+
+if (res != MEMTX_OK) {
+return res;
+}
+
+valid_l2t = (value >> VALID_SHIFT) & VALID_MASK;
+
+if (valid_l2t) {
+max_l2_entries = s->dt.page_sz / s->dt.entry_sz;
+
+

[PATCH v4 0/8] GICv3 LPI and ITS feature implementation

2021-06-02 Thread Shashi Mallela
This patchset implements qemu device model for enabling physical
LPI support and ITS functionality in GIC as per GICv3 specification.
Both flat table and 2 level tables are implemented.The ITS commands
for adding/deleting ITS table entries,trigerring LPI interrupts are
implemented.Translated LPI interrupt ids are processed by redistributor
to determine priority and set pending state appropriately before
forwarding the same to cpu interface.
The ITS feature support has been added to sbsa-ref platform as well as
virt platform,wherein the emulated functionality co-exists with kvm
kernel functionality.

Changes in v4:
 - review comments addressed
 - redesigned the lpi pending priority determination logic to scan
   LPI pending table and config table right after lpi pending
   statechanges(SET/RESET) through gicv3_redist_update_lpi() call to
   determinethe highest priority lpi among the active lpis and save
   the details.The high priority interrupt determination logic in
   redistributor now usesthe saved high priority lpi details
   (alongside other interrupt types) instead of calling
   gicv3_redist_update_lpi() everytime(as in v3).This
   significantly reduces the call overhead associated with
   address_space_read of lpi config and pending tables.
   Testing with this new design showed no boot delays.
 - profiled execution of gicv3_redist_update_lpi() using perf and
   framegraph to confirm execution is within normal limits.
   Also,specifically measured execution time to be an average of 175us
   with linux distro testing.
 - All kvm_unit_tests PASS

Shashi Mallela (8):
  hw/intc: GICv3 ITS initial framework
  hw/intc: GICv3 ITS register definitions added
  hw/intc: GICv3 ITS command queue framework
  hw/intc: GICv3 ITS Command processing
  hw/intc: GICv3 ITS Feature enablement
  hw/intc: GICv3 redistributor ITS processing
  hw/arm/sbsa-ref: add ITS support in SBSA GIC
  hw/arm/virt: add ITS support in virt GIC

 hw/arm/sbsa-ref.c  |   26 +-
 hw/arm/virt.c  |   27 +-
 hw/intc/arm_gicv3.c|9 +
 hw/intc/arm_gicv3_common.c |   13 +
 hw/intc/arm_gicv3_cpuif.c  |7 +-
 hw/intc/arm_gicv3_dist.c   |7 +-
 hw/intc/arm_gicv3_its.c| 1217 
 hw/intc/arm_gicv3_its_common.c |8 +-
 hw/intc/arm_gicv3_its_kvm.c|2 +-
 hw/intc/arm_gicv3_redist.c |  159 +++-
 hw/intc/gicv3_internal.h   |  186 +++-
 hw/intc/meson.build|1 +
 include/hw/arm/virt.h  |2 +
 include/hw/intc/arm_gicv3_common.h |   16 +
 include/hw/intc/arm_gicv3_its_common.h |   39 +-
 target/arm/kvm_arm.h   |4 +-
 16 files changed, 1694 insertions(+), 29 deletions(-)
 create mode 100644 hw/intc/arm_gicv3_its.c

-- 
2.27.0




[PATCH v4 2/8] hw/intc: GICv3 ITS register definitions added

2021-06-02 Thread Shashi Mallela
Defined descriptors for ITS device table,collection table and ITS
command queue entities.Implemented register read/write functions,
extract ITS table parameters and command queue parameters,extended
gicv3 common to capture qemu address space(which host the ITS table
platform memories required for subsequent ITS processing) and
initialize the same in ITS device.

Signed-off-by: Shashi Mallela 
---
 hw/intc/arm_gicv3_its.c| 335 +
 hw/intc/gicv3_internal.h   |  28 ++-
 include/hw/intc/arm_gicv3_common.h |   3 +
 include/hw/intc/arm_gicv3_its_common.h |  30 +++
 4 files changed, 395 insertions(+), 1 deletion(-)

diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c
index 545cda3665..af60f19c98 100644
--- a/hw/intc/arm_gicv3_its.c
+++ b/hw/intc/arm_gicv3_its.c
@@ -28,6 +28,157 @@ struct GICv3ITSClass {
 void (*parent_reset)(DeviceState *dev);
 };
 
+static uint64_t baser_base_addr(uint64_t value, uint32_t page_sz)
+{
+uint64_t result = 0;
+
+switch (page_sz) {
+case GITS_ITT_PAGE_SIZE_0:
+case GITS_ITT_PAGE_SIZE_1:
+result = value & R_GITS_BASER_PHYADDR_MASK;
+break;
+
+case GITS_ITT_PAGE_SIZE_2:
+result = value & R_GITS_BASER_PHYADDRL_64K_MASK;
+result |= FIELD_EX64(value, GITS_BASER, PHYADDRH_64K) << 48;
+break;
+
+default:
+break;
+}
+return result;
+}
+
+static void extract_table_params(GICv3ITSState *s)
+{
+uint16_t num_pages = 0;
+uint8_t  page_sz_type;
+uint8_t type;
+uint32_t page_sz = 0;
+uint64_t value;
+
+for (int i = 0; i < 8; i++) {
+value = s->baser[i];
+
+if (!value) {
+continue;
+}
+
+page_sz_type = FIELD_EX64(value, GITS_BASER, PAGESIZE);
+
+switch (page_sz_type) {
+case 0:
+page_sz = GITS_ITT_PAGE_SIZE_0;
+break;
+
+case 1:
+page_sz = GITS_ITT_PAGE_SIZE_1;
+break;
+
+case 2:
+case 3:
+page_sz = GITS_ITT_PAGE_SIZE_2;
+break;
+
+default:
+g_assert_not_reached();
+}
+
+num_pages = FIELD_EX64(value, GITS_BASER, SIZE);
+
+type = FIELD_EX64(value, GITS_BASER, TYPE);
+
+switch (type) {
+
+case GITS_ITT_TYPE_DEVICE:
+memset(>dt, 0 , sizeof(s->dt));
+s->dt.valid = FIELD_EX64(value, GITS_BASER, VALID);
+
+if (!s->dt.valid) {
+return;
+}
+
+s->dt.page_sz = page_sz;
+s->dt.indirect = FIELD_EX64(value, GITS_BASER, INDIRECT);
+s->dt.entry_sz = FIELD_EX64(value, GITS_BASER, ENTRYSIZE);
+
+if (!s->dt.indirect) {
+s->dt.max_entries = ((num_pages + 1) * page_sz) /
+ s->dt.entry_sz;
+} else {
+s->dt.max_entries = num_pages + 1) * page_sz) /
+ L1TABLE_ENTRY_SIZE) *
+ (page_sz / s->dt.entry_sz));
+}
+
+s->dt.max_devids = (1UL << (FIELD_EX64(s->typer, GITS_TYPER,
+DEVBITS) + 1));
+
+s->dt.base_addr = baser_base_addr(value, page_sz);
+
+break;
+
+case GITS_ITT_TYPE_COLLECTION:
+memset(>ct, 0 , sizeof(s->ct));
+s->ct.valid = FIELD_EX64(value, GITS_BASER, VALID);
+
+/*
+ * GITS_TYPER.HCC is 0 for this implementation
+ * hence writes are discarded if ct.valid is 0
+ */
+if (!s->ct.valid) {
+return;
+}
+
+s->ct.page_sz = page_sz;
+s->ct.indirect = FIELD_EX64(value, GITS_BASER, INDIRECT);
+s->ct.entry_sz = FIELD_EX64(value, GITS_BASER, ENTRYSIZE);
+
+if (!s->ct.indirect) {
+s->ct.max_entries = ((num_pages + 1) * page_sz) /
+ s->ct.entry_sz;
+} else {
+s->ct.max_entries = num_pages + 1) * page_sz) /
+ L1TABLE_ENTRY_SIZE) *
+ (page_sz / s->ct.entry_sz));
+}
+
+if (FIELD_EX64(s->typer, GITS_TYPER, CIL)) {
+s->ct.max_collids = (1UL << (FIELD_EX64(s->typer,
+ GITS_TYPER, CIDBITS) + 1));
+} else {
+/* 16-bit CollectionId supported when CIL == 0 */
+s->ct.max_collids = (1UL << 16);
+}
+
+s->ct.base_addr = baser_base_addr(value, page_sz);
+
+break;
+
+default:
+break;
+}
+}
+}
+
+static void extract_cmdq_params(GICv3ITSState *s)
+{
+uint16_t num_pages = 0;
+uint64_t value = s->cbaser;
+
+num_pages = FIELD_EX64(value, GITS_CBASER, SIZE);
+
+memset(>cq, 0 , sizeof(s->cq));
+s->cq.valid 

[PATCH v4 1/8] hw/intc: GICv3 ITS initial framework

2021-06-02 Thread Shashi Mallela
Added register definitions relevant to ITS,implemented overall
ITS device framework with stubs for ITS control and translater
regions read/write,extended ITS common to handle mmio init between
existing kvm device and newer qemu device.

Signed-off-by: Shashi Mallela 
---
 hw/intc/arm_gicv3_its.c| 240 +
 hw/intc/arm_gicv3_its_common.c |   8 +-
 hw/intc/arm_gicv3_its_kvm.c|   2 +-
 hw/intc/gicv3_internal.h   |  88 +++--
 hw/intc/meson.build|   1 +
 include/hw/intc/arm_gicv3_its_common.h |   9 +-
 6 files changed, 331 insertions(+), 17 deletions(-)
 create mode 100644 hw/intc/arm_gicv3_its.c

diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c
new file mode 100644
index 00..545cda3665
--- /dev/null
+++ b/hw/intc/arm_gicv3_its.c
@@ -0,0 +1,240 @@
+/*
+ * ITS emulation for a GICv3-based system
+ *
+ * Copyright Linaro.org 2021
+ *
+ * Authors:
+ *  Shashi Mallela 
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or (at your
+ * option) any later version.  See the COPYING file in the top-level directory.
+ *
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/log.h"
+#include "hw/qdev-properties.h"
+#include "hw/intc/arm_gicv3_its_common.h"
+#include "gicv3_internal.h"
+#include "qom/object.h"
+
+typedef struct GICv3ITSClass GICv3ITSClass;
+/* This is reusing the GICv3ITSState typedef from ARM_GICV3_ITS_COMMON */
+DECLARE_OBJ_CHECKERS(GICv3ITSState, GICv3ITSClass,
+ ARM_GICV3_ITS, TYPE_ARM_GICV3_ITS)
+
+struct GICv3ITSClass {
+GICv3ITSCommonClass parent_class;
+void (*parent_reset)(DeviceState *dev);
+};
+
+static MemTxResult gicv3_its_translation_write(void *opaque, hwaddr offset,
+   uint64_t data, unsigned size,
+   MemTxAttrs attrs)
+{
+MemTxResult result = MEMTX_OK;
+
+return result;
+}
+
+static MemTxResult its_writel(GICv3ITSState *s, hwaddr offset,
+  uint64_t value, MemTxAttrs attrs)
+{
+MemTxResult result = MEMTX_OK;
+
+return result;
+}
+
+static MemTxResult its_readl(GICv3ITSState *s, hwaddr offset,
+ uint64_t *data, MemTxAttrs attrs)
+{
+MemTxResult result = MEMTX_OK;
+
+return result;
+}
+
+static MemTxResult its_writell(GICv3ITSState *s, hwaddr offset,
+   uint64_t value, MemTxAttrs attrs)
+{
+MemTxResult result = MEMTX_OK;
+
+return result;
+}
+
+static MemTxResult its_readll(GICv3ITSState *s, hwaddr offset,
+  uint64_t *data, MemTxAttrs attrs)
+{
+MemTxResult result = MEMTX_OK;
+
+return result;
+}
+
+static MemTxResult gicv3_its_read(void *opaque, hwaddr offset, uint64_t *data,
+  unsigned size, MemTxAttrs attrs)
+{
+GICv3ITSState *s = (GICv3ITSState *)opaque;
+MemTxResult result;
+
+switch (size) {
+case 4:
+result = its_readl(s, offset, data, attrs);
+break;
+case 8:
+result = its_readll(s, offset, data, attrs);
+break;
+default:
+result = MEMTX_ERROR;
+break;
+}
+
+if (result == MEMTX_ERROR) {
+qemu_log_mask(LOG_GUEST_ERROR,
+  "%s: invalid guest read at offset " TARGET_FMT_plx
+  "size %u\n", __func__, offset, size);
+/*
+ * The spec requires that reserved registers are RAZ/WI;
+ * so use MEMTX_ERROR returns from leaf functions as a way to
+ * trigger the guest-error logging but don't return it to
+ * the caller, or we'll cause a spurious guest data abort.
+ */
+result = MEMTX_OK;
+*data = 0;
+}
+return result;
+}
+
+static MemTxResult gicv3_its_write(void *opaque, hwaddr offset, uint64_t data,
+   unsigned size, MemTxAttrs attrs)
+{
+GICv3ITSState *s = (GICv3ITSState *)opaque;
+MemTxResult result;
+
+switch (size) {
+case 4:
+result = its_writel(s, offset, data, attrs);
+break;
+case 8:
+result = its_writell(s, offset, data, attrs);
+break;
+default:
+result = MEMTX_ERROR;
+break;
+}
+
+if (result == MEMTX_ERROR) {
+qemu_log_mask(LOG_GUEST_ERROR,
+  "%s: invalid guest write at offset " TARGET_FMT_plx
+  "size %u\n", __func__, offset, size);
+/*
+ * The spec requires that reserved registers are RAZ/WI;
+ * so use MEMTX_ERROR returns from leaf functions as a way to
+ * trigger the guest-error logging but don't return it to
+ * the caller, or we'll cause a spurious guest data abort.
+ */
+result = MEMTX_OK;
+}
+return result;
+}
+
+static const MemoryRegionOps gicv3_its_control_ops = {
+.read_with_attrs = gicv3_its_read,
+.write_with_attrs = 

Re: [PATCH v7 09/27] tcg/tci: Improve tcg_target_call_clobber_regs

2021-06-02 Thread Philippe Mathieu-Daudé
On 6/1/21 5:00 PM, Richard Henderson wrote:
> The current setting is much too pessimistic.  Indicating only
> the one or two registers that are actually assigned after a
> call should avoid unnecessary movement between the register
> array and the stack array.
> 
> Tested-by: Philippe Mathieu-Daudé 
> Signed-off-by: Richard Henderson 
> ---
>  tcg/tci/tcg-target.c.inc | 10 --
>  1 file changed, 8 insertions(+), 2 deletions(-)

Reviewed-by: Philippe Mathieu-Daudé 



Re: [PATCH v3 0/8] GICv3 LPI and ITS feature implementation

2021-06-02 Thread Shashi Mallela
This is due to missing IORT acpi data,applicable with latest ITS changes.
Will be sharing a separate review with new files.

On May 18 2021, at 10:46 am, Peter Maydell  wrote:
> On Fri, 30 Apr 2021 at 00:42, Shashi Mallela  
> wrote:
> >
> > This patchset implements qemu device model for enabling physical
> > LPI support and ITS functionality in GIC as per GICv3 specification.
> > Both flat table and 2 level tables are implemented.The ITS commands
> > for adding/deleting ITS table entries,trigerring LPI interrupts are
> > implemented.Translated LPI interrupt ids are processed by redistributor
> > to determine priority and set pending state appropriately before
> > forwarding the same to cpu interface.
> > The ITS feature support has been added to sbsa-ref platform as well as
> > virt platform,wherein the emulated functionality co-exists with kvm
> > kernel functionality.
> >
> > Changes in v3:
> > - review comments addressed
> >
> > Shashi Mallela (8):
> > hw/intc: GICv3 ITS initial framework
> > hw/intc: GICv3 ITS register definitions added
> > hw/intc: GICv3 ITS command queue framework
> > hw/intc: GICv3 ITS Command processing
> > hw/intc: GICv3 ITS Feature enablement
> > hw/intc: GICv3 redistributor ITS processing
> > hw/arm/sbsa-ref: add ITS support in SBSA GIC
> > hw/arm/virt: add ITS support in virt GIC
>
> Something in here breaks "make check":
> MALLOC_PERTURB_=${MALLOC_PERTURB_:-$(( ${RANDOM:-0} % 255 + 1))}
> QTEST_QEMU_IMG=./qemu-img
> G_TEST_DBUS_DAEMON=/home/petmay01/linaro/qemu-from-laptop/qemu/tests/dbus-vmstate-daemon.sh
> QTEST_QEMU_BINARY=./qemu-system-aarch64 tests/qtest/bios-tables-test
> --tap -k
>
> Looking for expected file 'tests/data/acpi/virt/FACP'
> Using expected file 'tests/data/acpi/virt/FACP'
> Looking for expected file 'tests/data/acpi/virt/APIC'
> Using expected file 'tests/data/acpi/virt/APIC'
> Looking for expected file 'tests/data/acpi/virt/GTDT'
> Using expected file 'tests/data/acpi/virt/GTDT'
> Looking for expected file 'tests/data/acpi/virt/MCFG'
> Using expected file 'tests/data/acpi/virt/MCFG'
> Looking for expected file 'tests/data/acpi/virt/SPCR'
> Using expected file 'tests/data/acpi/virt/SPCR'
> Looking for expected file 'tests/data/acpi/virt/IORT'
> **
> ERROR:../../tests/qtest/bios-tables-test.c:385:load_expected_aml:
> assertion failed: (exp_sdt.aml_file)
> ERROR qtest-aarch64/bios-tables-test - Bail out!
> ERROR:../../tests/qtest/bios-tables-test.c:385:load_expected_aml:
> assertion failed: (exp_sdt.aml_file)
>
> (and then it hangs)
> -- PMM

  1   2   3   4   >