Re: [PATCH v2 17/20] smbios: clear smbios_type4_count before building tables

2024-03-05 Thread Ani Sinha



> On 05-Mar-2024, at 21:27, Igor Mammedov  wrote:
> 
> it will help to keep type 4 tables accounting correct in case
> SMBIOS tables are built multiple times.


I suggest you arrange this before patch 15 where you are actually calling 
smbios_get_tables_ep() multiple times. That way there is no window where things 
can break between patches.

> 
> Signed-off-by: Igor Mammedov 
> Tested-by: Fiona Ebner 
> ---
> hw/smbios/smbios.c | 1 +
> 1 file changed, 1 insertion(+)
> 
> diff --git a/hw/smbios/smbios.c b/hw/smbios/smbios.c
> index bf5c7a8885..b64d3bc227 100644
> --- a/hw/smbios/smbios.c
> +++ b/hw/smbios/smbios.c
> @@ -981,6 +981,7 @@ static bool smbios_get_tables_ep(MachineState *ms,
>ep_type == SMBIOS_ENTRY_POINT_TYPE_64);
> 
> g_free(smbios_tables);
> +smbios_type4_count = 0;

Nit: Can you put this before g_free() because gfree(smbios_tables) and 
smbios_tables = memdup2() etc are related. This is kind of coming in between.

> smbios_tables = g_memdup2(usr_blobs, usr_blobs_len);
> smbios_tables_len = usr_blobs_len;
> smbios_table_max = usr_table_max;
> -- 
> 2.39.3
> 




Re: [PATCH V2 1/1] target/loongarch: Fixed tlb huge page loading issue

2024-03-05 Thread maobibo

Sorry, manual is updated already and we do not notice that still.

https://www.loongson.cn/uploads/images/2023102309132647981.%E9%BE%99%E8%8A%AF%E6%9E%B6%E6%9E%84%E5%8F%82%E8%80%83%E6%89%8B%E5%86%8C%E5%8D%B7%E4%B8%80_r1p10.pdf

It is Chinese web link, English manual is not updated. Here is English 
translation by manual with instruction  "lddir rd, rj, level"


If the bit[14:13] of the register rj is not equal to 0 and its bit[6] 
is 1, the value of the register rj is a marked as HugePage page entries. 
In this case, the value from register rj is written directly to register rd.


If the bit[14:13] of the register rj is equal to 0 and its bit[6] is 1, 
the value of the register rj is an Hugepage table entry. In this case, 
replace the bit[14:13] of the register RJ value with level[1:0], the val 
is written to the register rd.


If the bit[6] bit of register rj is 0, the value of the universal 
register rj is the page table entry, it is  physical address base page 
table. In this case, if the LDDIR command is executed, the address will 
be refilled according to the TLB currently processed. Retrieve the base 
address of the next-level page table and write it to the common register 
rd.


We will remove temporary lddir_ps, and record page size with bit[14:13] 
in next version.


Regards
Bibo Mao

On 2024/3/6 下午12:10, Richard Henderson wrote:

On 3/5/24 17:52, lixianglai wrote:
The LDDIR_PS variable is not described in detail in the manual, but is 
only an intermediate variable to assist in page size calculation 
during tcg simulation.


This is exactly why I believe adding this intermediate variable is wrong.

What happens if LDPTE is *not* preceded by LDDIR?  It's not the usual 
way a tlb fill routine works, but *something* should happen if you 
construct a valid huge page tlb entry by hand and pass it directly to 
LDPTE.


With your implementation, this will not work because lddir_ps will not 
be initialized. But I expect that on real hardware it would work.


If this does not work on real hardware, then there *is* some heretofore 
undocumented hardware state.  If so, then we need a description of this 
state from the hardware engineers -- the documentation of LDDIR and 
LDPTE need updating.  Finally, this new hardware state needs to be added 
to the migration state.



r~





Re: [PATCH v1 0/8] virtio,vhost: Add VIRTIO_F_NOTIFICATION_DATA support

2024-03-05 Thread Michael S. Tsirkin
On Wed, Mar 06, 2024 at 08:07:31AM +0100, Eugenio Perez Martin wrote:
> On Wed, Mar 6, 2024 at 6:34 AM Jason Wang  wrote:
> >
> > On Tue, Mar 5, 2024 at 3:46 AM Jonah Palmer  wrote:
> > >
> > > The goal of these patches are to add support to a variety of virtio and
> > > vhost devices for the VIRTIO_F_NOTIFICATION_DATA transport feature. This
> > > feature indicates that a driver will pass extra data (instead of just a
> > > virtqueue's index) when notifying the corresponding device.
> > >
> > > The data passed in by the driver when this feature is enabled varies in
> > > format depending on if the device is using a split or packed virtqueue
> > > layout:
> > >
> > >  Split VQ
> > >   - Upper 16 bits: shadow_avail_idx
> > >   - Lower 16 bits: virtqueue index
> > >
> > >  Packed VQ
> > >   - Upper 16 bits: 1-bit wrap counter & 15-bit shadow_avail_idx
> > >   - Lower 16 bits: virtqueue index
> > >
> > > Also, due to the limitations of ioeventfd not being able to carry the
> > > extra provided by the driver, ioeventfd is left disabled for any devices
> > > using this feature.
> >
> > Is there any method to overcome this? This might help for vhost.
> >
> 
> As a half-baked idea, read(2)ing an eventfd descriptor returns an
> 8-byte integer already. The returned value of read depends on eventfd
> flags, but both have to do with the number of writes of the other end.
> 
> My proposal is to replace this value with the last value written by
> the guest, so we can extract the virtio notification data from there.
> The behavior of read is similar to not-EFD_SEMAPHORE, reading a value
> and then blocking if read again without writes. The behavior of KVM
> writes is different, as it is not a counter anymore.
> 
> Thanks!


I doubt you will be able to support this in ioeventfd...
But vhost does not really need the value at all.
So why mask out ioeventfd with vhost?
vhost-vdpa is probably the only one that might need it...



> > Thanks
> >
> > >
> > > A significant aspect of this effort has been to maintain compatibility
> > > across different backends. As such, the feature is offered by backend
> > > devices only when supported, with fallback mechanisms where backend
> > > support is absent.
> > >
> > > Jonah Palmer (8):
> > >   virtio/virtio-pci: Handle extra notification data
> > >   virtio-pci: Lock ioeventfd state with VIRTIO_F_NOTIFICATION_DATA
> > >   virtio-mmio: Handle extra notification data
> > >   virtio-mmio: Lock ioeventfd state with VIRTIO_F_NOTIFICATION_DATA
> > >   virtio-ccw: Handle extra notification data
> > >   virtio-ccw: Lock ioeventfd state with VIRTIO_F_NOTIFICATION_DATA
> > >   vhost/vhost-user: Add VIRTIO_F_NOTIFICATION_DATA to vhost feature bits
> > >   virtio: Add VIRTIO_F_NOTIFICATION_DATA property definition
> > >
> > >  hw/block/vhost-user-blk.c|  1 +
> > >  hw/net/vhost_net.c   |  2 ++
> > >  hw/s390x/s390-virtio-ccw.c   | 16 
> > >  hw/s390x/virtio-ccw.c|  6 --
> > >  hw/scsi/vhost-scsi.c |  1 +
> > >  hw/scsi/vhost-user-scsi.c|  1 +
> > >  hw/virtio/vhost-user-fs.c|  2 +-
> > >  hw/virtio/vhost-user-vsock.c |  1 +
> > >  hw/virtio/virtio-mmio.c  | 15 +++
> > >  hw/virtio/virtio-pci.c   | 16 +++-
> > >  hw/virtio/virtio.c   | 18 ++
> > >  include/hw/virtio/virtio.h   |  5 -
> > >  net/vhost-vdpa.c |  1 +
> > >  13 files changed, 68 insertions(+), 17 deletions(-)
> > >
> > > --
> > > 2.39.3
> > >
> >




Re: [PATCH v2 11/20] smbios: build legacy mode code only for 'pc' machine

2024-03-05 Thread Ani Sinha



> On 05-Mar-2024, at 21:27, Igor Mammedov  wrote:
> 
> basically moving code around without functional change.
> And exposing some symbols so that they could be shared
> between smbbios.c and new smbios_legacy.c
> 
> plus some meson magic to build smbios_legacy.c only
> for 'pc' machine and otherwise replace it with stub
> if not selected.

When I apply this, I get:

Applying: smbios: build legacy mode code only for 'pc' machine
.git/rebase-apply/patch:483: new blank line at EOF.
+
warning: 1 line adds whitespace errors.

Can you please look into this? Modulo that,

> 
> Signed-off-by: Igor Mammedov 

Reviewed-by: Ani Sinha 

> ---
> v2:
>  moved type0/type1/have_binfile_bitmap/have_fields_bitmap rename into
>  a separate patch
> ---
> include/hw/firmware/smbios.h   |   5 +
> hw/i386/Kconfig|   1 +
> hw/smbios/Kconfig  |   2 +
> hw/smbios/meson.build  |   4 +
> hw/smbios/smbios.c | 164 +-
> hw/smbios/smbios_legacy.c  | 179 +
> hw/smbios/smbios_legacy_stub.c |  16 +++
> 7 files changed, 208 insertions(+), 163 deletions(-)
> create mode 100644 hw/smbios/smbios_legacy.c
> create mode 100644 hw/smbios/smbios_legacy_stub.c
> 
> diff --git a/include/hw/firmware/smbios.h b/include/hw/firmware/smbios.h
> index bea5c3f1b1..7f47475aa4 100644
> --- a/include/hw/firmware/smbios.h
> +++ b/include/hw/firmware/smbios.h
> @@ -17,6 +17,9 @@
>  *
>  */
> 
> +extern uint8_t *usr_blobs;
> +extern GArray *usr_blobs_sizes;
> +
> typedef struct {
> const char *vendor, *version, *date;
> bool have_major_minor, uefi;
> @@ -306,6 +309,8 @@ struct smbios_type_127 {
> struct smbios_structure_header header;
> } QEMU_PACKED;
> 
> +void smbios_validate_table(void);
> +void smbios_add_usr_blob_size(size_t size);
> void smbios_entry_add(QemuOpts *opts, Error **errp);
> void smbios_set_cpuid(uint32_t version, uint32_t features);
> void smbios_set_defaults(const char *manufacturer, const char *product,
> diff --git a/hw/i386/Kconfig b/hw/i386/Kconfig
> index a1846be6f7..a6ee052f9a 100644
> --- a/hw/i386/Kconfig
> +++ b/hw/i386/Kconfig
> @@ -76,6 +76,7 @@ config I440FX
> select PIIX
> select DIMM
> select SMBIOS
> +select SMBIOS_LEGACY
> select FW_CFG_DMA
> 
> config ISAPC
> diff --git a/hw/smbios/Kconfig b/hw/smbios/Kconfig
> index 553adf4bfc..8d989a2f1b 100644
> --- a/hw/smbios/Kconfig
> +++ b/hw/smbios/Kconfig
> @@ -1,2 +1,4 @@
> config SMBIOS
> bool
> +config SMBIOS_LEGACY
> +bool
> diff --git a/hw/smbios/meson.build b/hw/smbios/meson.build
> index 7046967462..a59039f669 100644
> --- a/hw/smbios/meson.build
> +++ b/hw/smbios/meson.build
> @@ -4,5 +4,9 @@ smbios_ss.add(when: 'CONFIG_IPMI',
>   if_true: files('smbios_type_38.c'),
>   if_false: files('smbios_type_38-stub.c'))
> 
> +smbios_ss.add(when: 'CONFIG_SMBIOS_LEGACY',
> +  if_true: files('smbios_legacy.c'),
> +  if_false: files('smbios_legacy_stub.c'))
> +
> system_ss.add_all(when: 'CONFIG_SMBIOS', if_true: smbios_ss)
> system_ss.add(when: 'CONFIG_SMBIOS', if_false: files('smbios-stub.c'))
> diff --git a/hw/smbios/smbios.c b/hw/smbios/smbios.c
> index 86cf66b5ce..fb1f05fcde 100644
> --- a/hw/smbios/smbios.c
> +++ b/hw/smbios/smbios.c
> @@ -31,38 +31,12 @@
> #include "hw/pci/pci_device.h"
> #include "smbios_build.h"
> 
> -/* legacy structures and constants for <= 2.0 machines */
> -struct smbios_header {
> -uint16_t length;
> -uint8_t type;
> -} QEMU_PACKED;
> -
> -struct smbios_field {
> -struct smbios_header header;
> -uint8_t type;
> -uint16_t offset;
> -uint8_t data[];
> -} QEMU_PACKED;
> -
> -struct smbios_table {
> -struct smbios_header header;
> -uint8_t data[];
> -} QEMU_PACKED;
> -
> -#define SMBIOS_FIELD_ENTRY 0
> -#define SMBIOS_TABLE_ENTRY 1
> -
> -static uint8_t *smbios_entries;
> -static size_t smbios_entries_len;
> static bool smbios_uuid_encoded = true;
> -/* end: legacy structures & constants for <= 2.0 machines */
> -
> /*
>  * SMBIOS tables provided by user with '-smbios file=' option
>  */
> uint8_t *usr_blobs;
> size_t usr_blobs_len;
> -static GArray *usr_blobs_sizes;
> static unsigned usr_table_max;
> static unsigned usr_table_cnt;
> 
> @@ -483,7 +457,7 @@ static void smbios_check_type4_count(uint32_t 
> expected_t4_count)
> }
> }
> 
> -static void smbios_validate_table(void)
> +void smbios_validate_table(void)
> {
> if (smbios_ep_type == SMBIOS_ENTRY_POINT_TYPE_32 &&
> smbios_tables_len > SMBIOS_21_MAX_TABLES_LEN) {
> @@ -493,134 +467,6 @@ static void smbios_validate_table(void)
> }
> }
> 
> -
> -/* legacy setup functions for <= 2.0 machines */
> -static void smbios_add_field(int type, int offset, const void *data, size_t 
> len)
> -{
> -struct smbios_field *field;
> -
> -if (!smbios_entries) {
> -smbios_entries_len = sizeof(uint16_t);
> -smbios_entries = g_malloc0(smbios_entries_len);
> 

Re: [PATCH v2 10/20] smbios: rename/expose structures/bitmaps used by both legacy and modern code

2024-03-05 Thread Ani Sinha



On Tue, 5 Mar 2024, Igor Mammedov wrote:

> As a preparation to move legacy handling into a separate file,
> add prefix 'smbios_' to type0/type1/have_binfile_bitmap/have_fields_bitmap
> and expose them in smbios.h so that they can be reused in
> legacy and modern code.
>
> Doing it as a separate patch to avoid rename cluttering follow-up
> patch which will move legacy code into a separate file.
>

I checked that after application of this patch in the patcset, QEMU build
goes through fine. Therefore,

> Signed-off-by: Igor Mammedov 

Reviewed-by: Ani Sinha 

> ---
>  include/hw/firmware/smbios.h |  16 +
>  hw/smbios/smbios.c   | 113 ---
>  2 files changed, 69 insertions(+), 60 deletions(-)
>
> diff --git a/include/hw/firmware/smbios.h b/include/hw/firmware/smbios.h
> index 1fbff3c55f..bea5c3f1b1 100644
> --- a/include/hw/firmware/smbios.h
> +++ b/include/hw/firmware/smbios.h
> @@ -2,6 +2,7 @@
>  #define QEMU_SMBIOS_H
>
>  #include "qapi/qapi-types-machine.h"
> +#include "qemu/bitmap.h"
>
>  /*
>   * SMBIOS Support
> @@ -16,8 +17,23 @@
>   *
>   */
>
> +typedef struct {
> +const char *vendor, *version, *date;
> +bool have_major_minor, uefi;
> +uint8_t major, minor;
> +} smbios_type0_t;
> +extern smbios_type0_t smbios_type0;
> +
> +typedef struct {
> +const char *manufacturer, *product, *version, *serial, *sku, *family;
> +/* uuid is in qemu_uuid */
> +} smbios_type1_t;
> +extern smbios_type1_t smbios_type1;
>
>  #define SMBIOS_MAX_TYPE 127
> +extern DECLARE_BITMAP(smbios_have_binfile_bitmap, SMBIOS_MAX_TYPE + 1);
> +extern DECLARE_BITMAP(smbios_have_fields_bitmap, SMBIOS_MAX_TYPE + 1);
> +
>  #define offsetofend(TYPE, MEMBER) \
> (offsetof(TYPE, MEMBER) + sizeof_field(TYPE, MEMBER))
>
> diff --git a/hw/smbios/smbios.c b/hw/smbios/smbios.c
> index 01180bd82c..86cf66b5ce 100644
> --- a/hw/smbios/smbios.c
> +++ b/hw/smbios/smbios.c
> @@ -78,19 +78,11 @@ static int smbios_type4_count = 0;
>  static bool smbios_have_defaults;
>  static uint32_t smbios_cpuid_version, smbios_cpuid_features;
>
> -static DECLARE_BITMAP(have_binfile_bitmap, SMBIOS_MAX_TYPE+1);
> -static DECLARE_BITMAP(have_fields_bitmap, SMBIOS_MAX_TYPE+1);
> +DECLARE_BITMAP(smbios_have_binfile_bitmap, SMBIOS_MAX_TYPE + 1);
> +DECLARE_BITMAP(smbios_have_fields_bitmap, SMBIOS_MAX_TYPE + 1);
>
> -static struct {
> -const char *vendor, *version, *date;
> -bool have_major_minor, uefi;
> -uint8_t major, minor;
> -} type0;
> -
> -static struct {
> -const char *manufacturer, *product, *version, *serial, *sku, *family;
> -/* uuid is in qemu_uuid */
> -} type1;
> +smbios_type0_t smbios_type0;
> +smbios_type1_t smbios_type1;
>
>  static struct {
>  const char *manufacturer, *product, *version, *serial, *asset, *location;
> @@ -536,36 +528,36 @@ static void smbios_maybe_add_str(int type, int offset, 
> const char *data)
>  static void smbios_build_type_0_fields(void)
>  {
>  smbios_maybe_add_str(0, offsetof(struct smbios_type_0, vendor_str),
> - type0.vendor);
> + smbios_type0.vendor);
>  smbios_maybe_add_str(0, offsetof(struct smbios_type_0, bios_version_str),
> - type0.version);
> + smbios_type0.version);
>  smbios_maybe_add_str(0, offsetof(struct smbios_type_0,
>   bios_release_date_str),
> - type0.date);
> -if (type0.have_major_minor) {
> + smbios_type0.date);
> +if (smbios_type0.have_major_minor) {
>  smbios_add_field(0, offsetof(struct smbios_type_0,
>   system_bios_major_release),
> - , 1);
> + _type0.major, 1);
>  smbios_add_field(0, offsetof(struct smbios_type_0,
>   system_bios_minor_release),
> - , 1);
> + _type0.minor, 1);
>  }
>  }
>
>  static void smbios_build_type_1_fields(void)
>  {
>  smbios_maybe_add_str(1, offsetof(struct smbios_type_1, manufacturer_str),
> - type1.manufacturer);
> + smbios_type1.manufacturer);
>  smbios_maybe_add_str(1, offsetof(struct smbios_type_1, product_name_str),
> - type1.product);
> + smbios_type1.product);
>  smbios_maybe_add_str(1, offsetof(struct smbios_type_1, version_str),
> - type1.version);
> + smbios_type1.version);
>  smbios_maybe_add_str(1, offsetof(struct smbios_type_1, 
> serial_number_str),
> - type1.serial);
> + smbios_type1.serial);
>  smbios_maybe_add_str(1, offsetof(struct smbios_type_1, sku_number_str),
> - type1.sku);
> + smbios_type1.sku);
>  

Re: [PATCH v1 0/8] virtio, vhost: Add VIRTIO_F_NOTIFICATION_DATA support

2024-03-05 Thread Eugenio Perez Martin
On Wed, Mar 6, 2024 at 6:34 AM Jason Wang  wrote:
>
> On Tue, Mar 5, 2024 at 3:46 AM Jonah Palmer  wrote:
> >
> > The goal of these patches are to add support to a variety of virtio and
> > vhost devices for the VIRTIO_F_NOTIFICATION_DATA transport feature. This
> > feature indicates that a driver will pass extra data (instead of just a
> > virtqueue's index) when notifying the corresponding device.
> >
> > The data passed in by the driver when this feature is enabled varies in
> > format depending on if the device is using a split or packed virtqueue
> > layout:
> >
> >  Split VQ
> >   - Upper 16 bits: shadow_avail_idx
> >   - Lower 16 bits: virtqueue index
> >
> >  Packed VQ
> >   - Upper 16 bits: 1-bit wrap counter & 15-bit shadow_avail_idx
> >   - Lower 16 bits: virtqueue index
> >
> > Also, due to the limitations of ioeventfd not being able to carry the
> > extra provided by the driver, ioeventfd is left disabled for any devices
> > using this feature.
>
> Is there any method to overcome this? This might help for vhost.
>

As a half-baked idea, read(2)ing an eventfd descriptor returns an
8-byte integer already. The returned value of read depends on eventfd
flags, but both have to do with the number of writes of the other end.

My proposal is to replace this value with the last value written by
the guest, so we can extract the virtio notification data from there.
The behavior of read is similar to not-EFD_SEMAPHORE, reading a value
and then blocking if read again without writes. The behavior of KVM
writes is different, as it is not a counter anymore.

Thanks!

> Thanks
>
> >
> > A significant aspect of this effort has been to maintain compatibility
> > across different backends. As such, the feature is offered by backend
> > devices only when supported, with fallback mechanisms where backend
> > support is absent.
> >
> > Jonah Palmer (8):
> >   virtio/virtio-pci: Handle extra notification data
> >   virtio-pci: Lock ioeventfd state with VIRTIO_F_NOTIFICATION_DATA
> >   virtio-mmio: Handle extra notification data
> >   virtio-mmio: Lock ioeventfd state with VIRTIO_F_NOTIFICATION_DATA
> >   virtio-ccw: Handle extra notification data
> >   virtio-ccw: Lock ioeventfd state with VIRTIO_F_NOTIFICATION_DATA
> >   vhost/vhost-user: Add VIRTIO_F_NOTIFICATION_DATA to vhost feature bits
> >   virtio: Add VIRTIO_F_NOTIFICATION_DATA property definition
> >
> >  hw/block/vhost-user-blk.c|  1 +
> >  hw/net/vhost_net.c   |  2 ++
> >  hw/s390x/s390-virtio-ccw.c   | 16 
> >  hw/s390x/virtio-ccw.c|  6 --
> >  hw/scsi/vhost-scsi.c |  1 +
> >  hw/scsi/vhost-user-scsi.c|  1 +
> >  hw/virtio/vhost-user-fs.c|  2 +-
> >  hw/virtio/vhost-user-vsock.c |  1 +
> >  hw/virtio/virtio-mmio.c  | 15 +++
> >  hw/virtio/virtio-pci.c   | 16 +++-
> >  hw/virtio/virtio.c   | 18 ++
> >  include/hw/virtio/virtio.h   |  5 -
> >  net/vhost-vdpa.c |  1 +
> >  13 files changed, 68 insertions(+), 17 deletions(-)
> >
> > --
> > 2.39.3
> >
>




Re: [PATCH v2 09/20] smbios: add smbios_add_usr_blob_size() helper

2024-03-05 Thread Ani Sinha



> On 05-Mar-2024, at 21:27, Igor Mammedov  wrote:
> 
> it will be used by follow up patch when legacy handling
> is moved out into a separate file.
> 
> Signed-off-by: Igor Mammedov 

Reviewed-by: Ani Sinha 

> ---
> hw/smbios/smbios.c | 18 ++
> 1 file changed, 14 insertions(+), 4 deletions(-)
> 
> diff --git a/hw/smbios/smbios.c b/hw/smbios/smbios.c
> index 97cf762228..01180bd82c 100644
> --- a/hw/smbios/smbios.c
> +++ b/hw/smbios/smbios.c
> @@ -1287,6 +1287,14 @@ static bool save_opt_list(size_t *ndest, char ***dest, 
> QemuOpts *opts,
> return true;
> }
> 
> +static void smbios_add_usr_blob_size(size_t size)
> +{
> +if (!usr_blobs_sizes) {
> +usr_blobs_sizes = g_array_new(false, false, sizeof(size_t));
> +}
> +g_array_append_val(usr_blobs_sizes, size);
> +}
> +
> void smbios_entry_add(QemuOpts *opts, Error **errp)
> {
> const char *val;
> @@ -1334,10 +1342,12 @@ void smbios_entry_add(QemuOpts *opts, Error **errp)
> smbios_type4_count++;
> }
> 
> -if (!usr_blobs_sizes) {
> -usr_blobs_sizes = g_array_new(false, false, sizeof(size_t));
> -}
> -g_array_append_val(usr_blobs_sizes, size);
> +/*
> + * preserve blob size for legacy mode so it could build its
> + * blobs flavor from 'usr_blobs'
> + */
> +smbios_add_usr_blob_size(size);
> +
> usr_blobs_len += size;
> if (size > usr_table_max) {
> usr_table_max = size;
> -- 
> 2.39.3
> 




Re: [PATCH 2/2] linux-user/elfload: Fully initialize struct target_elf_prpsinfo

2024-03-05 Thread Philippe Mathieu-Daudé

On 6/3/24 00:39, Richard Henderson wrote:

Fixes Coverity CID: 1534962
Fixes: 243c4706625 ("linux-user/elfload: Write corefile elf header in one 
block")
Signed-off-by: Richard Henderson 
---
  linux-user/elfload.c | 16 
  1 file changed, 8 insertions(+), 8 deletions(-)


Reviewed-by: Philippe Mathieu-Daudé 




Re: [PATCH 1/2] linux-user/elfload: Don't close an unopened file descriptor

2024-03-05 Thread Philippe Mathieu-Daudé

On 6/3/24 00:39, Richard Henderson wrote:

Fixes Coverity CID: 1534964
Fixes: 106f8da664 ("linux-user/elfload: Open core file after vma_init")
Signed-off-by: Richard Henderson 
---
  linux-user/elfload.c | 4 +++-
  1 file changed, 3 insertions(+), 1 deletion(-)


Reviewed-by: Philippe Mathieu-Daudé 





Re: [PATCH v2 07/20] smbios: avoid mangling user provided tables

2024-03-05 Thread Ani Sinha



On Tue, 5 Mar 2024, Igor Mammedov wrote:

> currently smbios_entry_add() preserves internally '-smbios type='
> options but tables provided with '-smbios file=' are stored directly
> into blob that eventually will be exposed to VM. And then later
> QEMU adds default/'-smbios type' entries on top into the same blob.
>
> It makes impossible to generate tables more than once, hence
> 'immutable' guard was used.
> Make it possible to regenerate final blob by storing user provided
> blobs into a dedicated area (usr_blobs) and then copy it when
> composing final blob. Which also makes handling of -smbios
> options consistent.
>
> As side effect of this and previous commits there is no need to
> generate legacy smbios_entries at the time options are parsed.
> Instead compose smbios_entries on demand from  usr_blobs like
> it is done for non-legacy SMBIOS tables.
>
> Signed-off-by: Igor Mammedov 
> Tested-by: Fiona Ebner 

Reviewed-by: Ani Sinha 

> ---
>  hw/smbios/smbios.c | 179 +++--
>  1 file changed, 92 insertions(+), 87 deletions(-)
>
> diff --git a/hw/smbios/smbios.c b/hw/smbios/smbios.c
> index c46fc93357..aa2cc5bdbd 100644
> --- a/hw/smbios/smbios.c
> +++ b/hw/smbios/smbios.c
> @@ -57,6 +57,14 @@ static size_t smbios_entries_len;
>  static bool smbios_uuid_encoded = true;
>  /* end: legacy structures & constants for <= 2.0 machines */
>
> +/*
> + * SMBIOS tables provided by user with '-smbios file=' option
> + */
> +uint8_t *usr_blobs;
> +size_t usr_blobs_len;
> +static GArray *usr_blobs_sizes;
> +static unsigned usr_table_max;
> +static unsigned usr_table_cnt;
>
>  uint8_t *smbios_tables;
>  size_t smbios_tables_len;
> @@ -67,7 +75,6 @@ static SmbiosEntryPointType smbios_ep_type = 
> SMBIOS_ENTRY_POINT_TYPE_32;
>  static SmbiosEntryPoint ep;
>
>  static int smbios_type4_count = 0;
> -static bool smbios_immutable;
>  static bool smbios_have_defaults;
>  static uint32_t smbios_cpuid_version, smbios_cpuid_features;
>
> @@ -569,9 +576,8 @@ static void smbios_build_type_1_fields(void)
>
>  uint8_t *smbios_get_table_legacy(uint32_t expected_t4_count, size_t *length)
>  {
> -/* drop unwanted version of command-line file blob(s) */
> -g_free(smbios_tables);
> -smbios_tables = NULL;
> +int i;
> +size_t usr_offset;
>
>  /* also complain if fields were given for types > 1 */
>  if (find_next_bit(have_fields_bitmap,
> @@ -581,12 +587,33 @@ uint8_t *smbios_get_table_legacy(uint32_t 
> expected_t4_count, size_t *length)
>  exit(1);
>  }
>
> -if (!smbios_immutable) {
> -smbios_build_type_0_fields();
> -smbios_build_type_1_fields();
> -smbios_validate_table(expected_t4_count);
> -smbios_immutable = true;
> +g_free(smbios_entries);
> +smbios_entries_len = sizeof(uint16_t);
> +smbios_entries = g_malloc0(smbios_entries_len);
> +
> +for (i = 0, usr_offset = 0; usr_blobs_sizes && i < usr_blobs_sizes->len;
> + i++)
> +{
> +struct smbios_table *table;
> +struct smbios_structure_header *header;
> +size_t size = g_array_index(usr_blobs_sizes, size_t, i);
> +
> +header = (struct smbios_structure_header *)(usr_blobs + usr_offset);
> +smbios_entries = g_realloc(smbios_entries, smbios_entries_len +
> +   size + sizeof(*table));
> +table = (struct smbios_table *)(smbios_entries + smbios_entries_len);
> +table->header.type = SMBIOS_TABLE_ENTRY;
> +table->header.length = cpu_to_le16(sizeof(*table) + size);
> +memcpy(table->data, header, size);
> +smbios_entries_len += sizeof(*table) + size;
> +(*(uint16_t *)smbios_entries) =
> +cpu_to_le16(le16_to_cpu(*(uint16_t *)smbios_entries) + 1);

I know this comes from existing code but can you please explain why we add
1 to it? This is confusing and a comment here would be nice.

> +usr_offset += size;

It would be better if we could add a comment here describing a bit what
this is all about.

user blobs are an array of smbios_structure_header entries whereas legacy
tables are an array of smbios_table structures where
smbios_table->data represents the a single user provided table blob in
smbios_structure_header.

>  }
> +
> +smbios_build_type_0_fields();
> +smbios_build_type_1_fields();
> +smbios_validate_table(expected_t4_count);
>  *length = smbios_entries_len;
>  return smbios_entries;
>  }
> @@ -1094,67 +1121,67 @@ void smbios_get_tables(MachineState *ms,
>  {
>  unsigned i, dimm_cnt, offset;
>
> -/* drop unwanted (legacy) version of command-line file blob(s) */
> -g_free(smbios_entries);
> -smbios_entries = NULL;
> +g_free(smbios_tables);
> +smbios_tables = g_memdup2(usr_blobs, usr_blobs_len);

Again a comment describing here would be nice as to why memdup is ok.

> +smbios_tables_len = usr_blobs_len;
> +smbios_table_max = 

[PATCH v3 17/19] contrib/elf2dmp: Use GPtrArray

2024-03-05 Thread Akihiko Odaki
This removes the need to enumarate QEMUCPUState twice and saves code.

Signed-off-by: Akihiko Odaki 
Reviewed-by: Peter Maydell 
---
 contrib/elf2dmp/qemu_elf.c | 25 -
 1 file changed, 8 insertions(+), 17 deletions(-)

diff --git a/contrib/elf2dmp/qemu_elf.c b/contrib/elf2dmp/qemu_elf.c
index a22c057d3ec3..7d896cac5b15 100644
--- a/contrib/elf2dmp/qemu_elf.c
+++ b/contrib/elf2dmp/qemu_elf.c
@@ -66,7 +66,7 @@ static bool init_states(QEMU_Elf *qe)
 Elf64_Nhdr *start = (void *)((uint8_t *)qe->map + phdr[0].p_offset);
 Elf64_Nhdr *end = (void *)((uint8_t *)start + phdr[0].p_memsz);
 Elf64_Nhdr *nhdr;
-size_t cpu_nr = 0;
+GPtrArray *states;
 
 if (phdr[0].p_type != PT_NOTE) {
 eprintf("Failed to find PT_NOTE\n");
@@ -74,38 +74,29 @@ static bool init_states(QEMU_Elf *qe)
 }
 
 qe->has_kernel_gs_base = 1;
+states = g_ptr_array_new();
 
 for (nhdr = start; nhdr < end; nhdr = nhdr_get_next(nhdr)) {
 if (!strcmp(nhdr_get_name(nhdr), QEMU_NOTE_NAME)) {
 QEMUCPUState *state = nhdr_get_desc(nhdr);
 
 if (state->size < sizeof(*state)) {
-eprintf("CPU #%zu: QEMU CPU state size %u doesn't match\n",
-cpu_nr, state->size);
+eprintf("CPU #%u: QEMU CPU state size %u doesn't match\n",
+states->len, state->size);
 /*
  * We assume either every QEMU CPU state has KERNEL_GS_BASE or
  * no one has.
  */
 qe->has_kernel_gs_base = 0;
 }
-cpu_nr++;
+g_ptr_array_add(states, state);
 }
 }
 
-printf("%zu CPU states has been found\n", cpu_nr);
+printf("%u CPU states has been found\n", states->len);
 
-qe->state = g_new(QEMUCPUState*, cpu_nr);
-
-cpu_nr = 0;
-
-for (nhdr = start; nhdr < end; nhdr = nhdr_get_next(nhdr)) {
-if (!strcmp(nhdr_get_name(nhdr), QEMU_NOTE_NAME)) {
-qe->state[cpu_nr] = nhdr_get_desc(nhdr);
-cpu_nr++;
-}
-}
-
-qe->state_nr = cpu_nr;
+qe->state_nr = states->len;
+qe->state = (void *)g_ptr_array_free(states, FALSE);
 
 return true;
 }

-- 
2.44.0




[PATCH v3 04/19] contrib/elf2dmp: Change pa_space_create() signature

2024-03-05 Thread Akihiko Odaki
pa_space_create() used to return an integer to propagate error, but
it never fails so let it return void.

Signed-off-by: Akihiko Odaki 
---
 contrib/elf2dmp/addrspace.h | 2 +-
 contrib/elf2dmp/addrspace.c | 4 +---
 contrib/elf2dmp/main.c  | 5 +
 3 files changed, 3 insertions(+), 8 deletions(-)

diff --git a/contrib/elf2dmp/addrspace.h b/contrib/elf2dmp/addrspace.h
index 039c70c5b079..c868d6473873 100644
--- a/contrib/elf2dmp/addrspace.h
+++ b/contrib/elf2dmp/addrspace.h
@@ -33,7 +33,7 @@ struct va_space {
 struct pa_space *ps;
 };
 
-int pa_space_create(struct pa_space *ps, QEMU_Elf *qemu_elf);
+void pa_space_create(struct pa_space *ps, QEMU_Elf *qemu_elf);
 void pa_space_destroy(struct pa_space *ps);
 
 void va_space_create(struct va_space *vs, struct pa_space *ps, uint64_t dtb);
diff --git a/contrib/elf2dmp/addrspace.c b/contrib/elf2dmp/addrspace.c
index 6f608a517b1e..4c127c9b1ec4 100644
--- a/contrib/elf2dmp/addrspace.c
+++ b/contrib/elf2dmp/addrspace.c
@@ -57,7 +57,7 @@ static void pa_block_align(struct pa_block *b)
 b->paddr += low_align;
 }
 
-int pa_space_create(struct pa_space *ps, QEMU_Elf *qemu_elf)
+void pa_space_create(struct pa_space *ps, QEMU_Elf *qemu_elf)
 {
 Elf64_Half phdr_nr = elf_getphdrnum(qemu_elf->map);
 Elf64_Phdr *phdr = elf64_getphdr(qemu_elf->map);
@@ -87,8 +87,6 @@ int pa_space_create(struct pa_space *ps, QEMU_Elf *qemu_elf)
 }
 
 ps->block_nr = block_i;
-
-return 0;
 }
 
 void pa_space_destroy(struct pa_space *ps)
diff --git a/contrib/elf2dmp/main.c b/contrib/elf2dmp/main.c
index 86e709e6da3a..8a71e2efd281 100644
--- a/contrib/elf2dmp/main.c
+++ b/contrib/elf2dmp/main.c
@@ -543,10 +543,7 @@ int main(int argc, char *argv[])
 return 1;
 }
 
-if (pa_space_create(, _elf)) {
-eprintf("Failed to initialize physical address space\n");
-goto out_elf;
-}
+pa_space_create(, _elf);
 
 state = qemu_elf.state[0];
 printf("CPU #0 CR3 is 0x%016"PRIx64"\n", state->cr[3]);

-- 
2.44.0




[PATCH v3 03/19] contrib/elf2dmp: Continue even contexts are lacking

2024-03-05 Thread Akihiko Odaki
Let fill_context() continue even if it fails to fill contexts of some
CPUs. A dump may still contain valuable information even if it lacks
contexts of some CPUs due to dump corruption or a failure before
starting CPUs.

Signed-off-by: Akihiko Odaki 
Reviewed-by: Peter Maydell 
---
 contrib/elf2dmp/main.c | 21 +++--
 1 file changed, 11 insertions(+), 10 deletions(-)

diff --git a/contrib/elf2dmp/main.c b/contrib/elf2dmp/main.c
index 9b278f392e39..86e709e6da3a 100644
--- a/contrib/elf2dmp/main.c
+++ b/contrib/elf2dmp/main.c
@@ -336,8 +336,13 @@ static int fill_header(WinDumpHeader64 *hdr, struct 
pa_space *ps,
 return 0;
 }
 
-static int fill_context(KDDEBUGGER_DATA64 *kdbg,
-struct va_space *vs, QEMU_Elf *qe)
+/*
+ * fill_context() continues even if it fails to fill contexts of some CPUs.
+ * A dump may still contain valuable information even if it lacks contexts of
+ * some CPUs due to dump corruption or a failure before starting CPUs.
+ */
+static void fill_context(KDDEBUGGER_DATA64 *kdbg,
+ struct va_space *vs, QEMU_Elf *qe)
 {
 int i;
 
@@ -350,7 +355,7 @@ static int fill_context(KDDEBUGGER_DATA64 *kdbg,
 if (va_space_rw(vs, kdbg->KiProcessorBlock + sizeof(Prcb) * i,
 , sizeof(Prcb), 0)) {
 eprintf("Failed to read CPU #%d PRCB location\n", i);
-return 1;
+continue;
 }
 
 if (!Prcb) {
@@ -361,7 +366,7 @@ static int fill_context(KDDEBUGGER_DATA64 *kdbg,
 if (va_space_rw(vs, Prcb + kdbg->OffsetPrcbContext,
 , sizeof(Context), 0)) {
 eprintf("Failed to read CPU #%d ContextFrame location\n", i);
-return 1;
+continue;
 }
 
 printf("Filling context for CPU #%d...\n", i);
@@ -369,11 +374,9 @@ static int fill_context(KDDEBUGGER_DATA64 *kdbg,
 
 if (va_space_rw(vs, Context, , sizeof(ctx), 1)) {
 eprintf("Failed to fill CPU #%d context\n", i);
-return 1;
+continue;
 }
 }
-
-return 0;
 }
 
 static int pe_get_data_dir_entry(uint64_t base, void *start_addr, int idx,
@@ -619,9 +622,7 @@ int main(int argc, char *argv[])
 goto out_kdbg;
 }
 
-if (fill_context(kdbg, , _elf)) {
-goto out_kdbg;
-}
+fill_context(kdbg, , _elf);
 
 if (write_dump(, , argv[2])) {
 eprintf("Failed to save dump\n");

-- 
2.44.0




[PATCH v3 18/19] contrib/elf2dmp: Clamp QEMU note to file size

2024-03-05 Thread Akihiko Odaki
This fixes crashes with truncated dumps.

Signed-off-by: Akihiko Odaki 
Reviewed-by: Peter Maydell 
---
 contrib/elf2dmp/qemu_elf.c | 87 +-
 1 file changed, 55 insertions(+), 32 deletions(-)

diff --git a/contrib/elf2dmp/qemu_elf.c b/contrib/elf2dmp/qemu_elf.c
index 7d896cac5b15..8d750adf904a 100644
--- a/contrib/elf2dmp/qemu_elf.c
+++ b/contrib/elf2dmp/qemu_elf.c
@@ -6,6 +6,7 @@
  */
 
 #include "qemu/osdep.h"
+#include "qemu/host-utils.h"
 #include "err.h"
 #include "qemu_elf.h"
 
@@ -15,36 +16,11 @@
 #define ROUND_UP(n, d) (((n) + (d) - 1) & -(0 ? (n) : (d)))
 #endif
 
-#ifndef DIV_ROUND_UP
-#define DIV_ROUND_UP(n, d) (((n) + (d) - 1) / (d))
-#endif
-
-#define ELF_NOTE_SIZE(hdr_size, name_size, desc_size)   \
-((DIV_ROUND_UP((hdr_size), 4) + \
-  DIV_ROUND_UP((name_size), 4) +\
-  DIV_ROUND_UP((desc_size), 4)) * 4)
-
 int is_system(QEMUCPUState *s)
 {
 return s->gs.base >> 63;
 }
 
-static char *nhdr_get_name(Elf64_Nhdr *nhdr)
-{
-return (char *)nhdr + ROUND_UP(sizeof(*nhdr), 4);
-}
-
-static void *nhdr_get_desc(Elf64_Nhdr *nhdr)
-{
-return nhdr_get_name(nhdr) + ROUND_UP(nhdr->n_namesz, 4);
-}
-
-static Elf64_Nhdr *nhdr_get_next(Elf64_Nhdr *nhdr)
-{
-return (void *)((uint8_t *)nhdr + ELF_NOTE_SIZE(sizeof(*nhdr),
-nhdr->n_namesz, nhdr->n_descsz));
-}
-
 Elf64_Phdr *elf64_getphdr(void *map)
 {
 Elf64_Ehdr *ehdr = map;
@@ -60,13 +36,35 @@ Elf64_Half elf_getphdrnum(void *map)
 return ehdr->e_phnum;
 }
 
+static bool advance_note_offset(uint64_t *offsetp, uint64_t size, uint64_t end)
+{
+uint64_t offset = *offsetp;
+
+if (uadd64_overflow(offset, size, ) || offset > UINT64_MAX - 3) {
+return false;
+}
+
+offset = ROUND_UP(offset, 4);
+
+if (offset > end) {
+return false;
+}
+
+*offsetp = offset;
+
+return true;
+}
+
 static bool init_states(QEMU_Elf *qe)
 {
 Elf64_Phdr *phdr = elf64_getphdr(qe->map);
-Elf64_Nhdr *start = (void *)((uint8_t *)qe->map + phdr[0].p_offset);
-Elf64_Nhdr *end = (void *)((uint8_t *)start + phdr[0].p_memsz);
 Elf64_Nhdr *nhdr;
 GPtrArray *states;
+QEMUCPUState *state;
+uint32_t state_size;
+uint64_t offset;
+uint64_t end_offset;
+char *name;
 
 if (phdr[0].p_type != PT_NOTE) {
 eprintf("Failed to find PT_NOTE\n");
@@ -74,15 +72,40 @@ static bool init_states(QEMU_Elf *qe)
 }
 
 qe->has_kernel_gs_base = 1;
+offset = phdr[0].p_offset;
 states = g_ptr_array_new();
 
-for (nhdr = start; nhdr < end; nhdr = nhdr_get_next(nhdr)) {
-if (!strcmp(nhdr_get_name(nhdr), QEMU_NOTE_NAME)) {
-QEMUCPUState *state = nhdr_get_desc(nhdr);
+if (uadd64_overflow(offset, phdr[0].p_memsz, _offset) ||
+end_offset > qe->size) {
+end_offset = qe->size;
+}
+
+while (offset < end_offset) {
+nhdr = (void *)((uint8_t *)qe->map + offset);
+
+if (!advance_note_offset(, sizeof(*nhdr), end_offset)) {
+break;
+}
+
+name = (char *)qe->map + offset;
+
+if (!advance_note_offset(, nhdr->n_namesz, end_offset)) {
+break;
+}
+
+state = (void *)((uint8_t *)qe->map + offset);
+
+if (!advance_note_offset(, nhdr->n_descsz, end_offset)) {
+break;
+}
+
+if (!strcmp(name, QEMU_NOTE_NAME) &&
+nhdr->n_descsz >= offsetof(QEMUCPUState, kernel_gs_base)) {
+state_size = MIN(state->size, nhdr->n_descsz);
 
-if (state->size < sizeof(*state)) {
+if (state_size < sizeof(*state)) {
 eprintf("CPU #%u: QEMU CPU state size %u doesn't match\n",
-states->len, state->size);
+states->len, state_size);
 /*
  * We assume either every QEMU CPU state has KERNEL_GS_BASE or
  * no one has.

-- 
2.44.0




[PATCH v3 06/19] contrib/elf2dmp: Fix error reporting style in download.c

2024-03-05 Thread Akihiko Odaki
include/qapi/error.h says:
> We recommend
> * bool-valued functions return true on success / false on failure,
> ...

Signed-off-by: Akihiko Odaki 
---
 contrib/elf2dmp/download.h |  2 +-
 contrib/elf2dmp/download.c | 10 +-
 contrib/elf2dmp/main.c |  2 +-
 3 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/contrib/elf2dmp/download.h b/contrib/elf2dmp/download.h
index 5c274925f7aa..f65adb5d0894 100644
--- a/contrib/elf2dmp/download.h
+++ b/contrib/elf2dmp/download.h
@@ -8,6 +8,6 @@
 #ifndef DOWNLOAD_H
 #define DOWNLOAD_H
 
-int download_url(const char *name, const char *url);
+bool download_url(const char *name, const char *url);
 
 #endif /* DOWNLOAD_H */
diff --git a/contrib/elf2dmp/download.c b/contrib/elf2dmp/download.c
index 902dc04ffa5c..21306b3fd4c4 100644
--- a/contrib/elf2dmp/download.c
+++ b/contrib/elf2dmp/download.c
@@ -9,14 +9,14 @@
 #include 
 #include "download.h"
 
-int download_url(const char *name, const char *url)
+bool download_url(const char *name, const char *url)
 {
-int err = 1;
+bool success = false;
 FILE *file;
 CURL *curl = curl_easy_init();
 
 if (!curl) {
-return 1;
+return false;
 }
 
 file = fopen(name, "wb");
@@ -33,11 +33,11 @@ int download_url(const char *name, const char *url)
 unlink(name);
 fclose(file);
 } else {
-err = fclose(file);
+success = !fclose(file);
 }
 
 out_curl:
 curl_easy_cleanup(curl);
 
-return err;
+return success;
 }
diff --git a/contrib/elf2dmp/main.c b/contrib/elf2dmp/main.c
index 09af39422f1e..d295fd92be2f 100644
--- a/contrib/elf2dmp/main.c
+++ b/contrib/elf2dmp/main.c
@@ -591,7 +591,7 @@ int main(int argc, char *argv[])
 sprintf(pdb_url, "%s%s/%s/%s", SYM_URL_BASE, PDB_NAME, pdb_hash, PDB_NAME);
 printf("PDB URL is %s\n", pdb_url);
 
-if (download_url(PDB_NAME, pdb_url)) {
+if (!download_url(PDB_NAME, pdb_url)) {
 eprintf("Failed to download PDB file\n");
 goto out_ps;
 }

-- 
2.44.0




[PATCH v3 13/19] contrib/elf2dmp: Use lduw_le_p() to read PDB

2024-03-05 Thread Akihiko Odaki
The relevant value may be unaligned and is little-endian.

Signed-off-by: Akihiko Odaki 
---
 contrib/elf2dmp/pdb.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/contrib/elf2dmp/pdb.c b/contrib/elf2dmp/pdb.c
index 1c5051425185..492aca4434c8 100644
--- a/contrib/elf2dmp/pdb.c
+++ b/contrib/elf2dmp/pdb.c
@@ -19,6 +19,7 @@
  */
 
 #include "qemu/osdep.h"
+#include "qemu/bswap.h"
 
 #include "pdb.h"
 #include "err.h"
@@ -186,7 +187,7 @@ static bool pdb_init_symbols(struct pdb_reader *r)
 
 r->symbols = symbols;
 
-r->segments = *(uint16_t *)((const char *)symbols + sizeof(PDB_SYMBOLS) +
+r->segments = lduw_le_p((const char *)symbols + sizeof(PDB_SYMBOLS) +
 symbols->module_size + symbols->offset_size +
 symbols->hash_size + symbols->srcmodule_size +
 symbols->pdbimport_size + symbols->unknown2_size +

-- 
2.44.0




[PATCH v3 08/19] contrib/elf2dmp: Fix error reporting style in qemu_elf.c

2024-03-05 Thread Akihiko Odaki
include/qapi/error.h says:
> We recommend
> * bool-valued functions return true on success / false on failure,
> ...

Signed-off-by: Akihiko Odaki 
---
 contrib/elf2dmp/qemu_elf.h |  2 +-
 contrib/elf2dmp/main.c |  2 +-
 contrib/elf2dmp/qemu_elf.c | 32 
 3 files changed, 18 insertions(+), 18 deletions(-)

diff --git a/contrib/elf2dmp/qemu_elf.h b/contrib/elf2dmp/qemu_elf.h
index afa75f10b2d2..adc50238b46b 100644
--- a/contrib/elf2dmp/qemu_elf.h
+++ b/contrib/elf2dmp/qemu_elf.h
@@ -42,7 +42,7 @@ typedef struct QEMU_Elf {
 int has_kernel_gs_base;
 } QEMU_Elf;
 
-int QEMU_Elf_init(QEMU_Elf *qe, const char *filename);
+bool QEMU_Elf_init(QEMU_Elf *qe, const char *filename);
 void QEMU_Elf_exit(QEMU_Elf *qe);
 
 Elf64_Phdr *elf64_getphdr(void *map);
diff --git a/contrib/elf2dmp/main.c b/contrib/elf2dmp/main.c
index 7a3a7225905e..cb28971789e4 100644
--- a/contrib/elf2dmp/main.c
+++ b/contrib/elf2dmp/main.c
@@ -535,7 +535,7 @@ int main(int argc, char *argv[])
 return 1;
 }
 
-if (QEMU_Elf_init(_elf, argv[1])) {
+if (!QEMU_Elf_init(_elf, argv[1])) {
 eprintf("Failed to initialize QEMU ELF dump\n");
 return 1;
 }
diff --git a/contrib/elf2dmp/qemu_elf.c b/contrib/elf2dmp/qemu_elf.c
index 055e6f8792e9..a22c057d3ec3 100644
--- a/contrib/elf2dmp/qemu_elf.c
+++ b/contrib/elf2dmp/qemu_elf.c
@@ -60,7 +60,7 @@ Elf64_Half elf_getphdrnum(void *map)
 return ehdr->e_phnum;
 }
 
-static int init_states(QEMU_Elf *qe)
+static bool init_states(QEMU_Elf *qe)
 {
 Elf64_Phdr *phdr = elf64_getphdr(qe->map);
 Elf64_Nhdr *start = (void *)((uint8_t *)qe->map + phdr[0].p_offset);
@@ -70,7 +70,7 @@ static int init_states(QEMU_Elf *qe)
 
 if (phdr[0].p_type != PT_NOTE) {
 eprintf("Failed to find PT_NOTE\n");
-return 1;
+return false;
 }
 
 qe->has_kernel_gs_base = 1;
@@ -107,7 +107,7 @@ static int init_states(QEMU_Elf *qe)
 
 qe->state_nr = cpu_nr;
 
-return 0;
+return true;
 }
 
 static void exit_states(QEMU_Elf *qe)
@@ -162,7 +162,7 @@ static bool check_ehdr(QEMU_Elf *qe)
 return true;
 }
 
-static int QEMU_Elf_map(QEMU_Elf *qe, const char *filename)
+static bool QEMU_Elf_map(QEMU_Elf *qe, const char *filename)
 {
 #ifdef CONFIG_LINUX
 struct stat st;
@@ -173,13 +173,13 @@ static int QEMU_Elf_map(QEMU_Elf *qe, const char 
*filename)
 fd = open(filename, O_RDONLY, 0);
 if (fd == -1) {
 eprintf("Failed to open ELF dump file \'%s\'\n", filename);
-return 1;
+return false;
 }
 
 if (fstat(fd, )) {
 eprintf("Failed to get size of ELF dump file\n");
 close(fd);
-return 1;
+return false;
 }
 qe->size = st.st_size;
 
@@ -188,7 +188,7 @@ static int QEMU_Elf_map(QEMU_Elf *qe, const char *filename)
 if (qe->map == MAP_FAILED) {
 eprintf("Failed to map ELF file\n");
 close(fd);
-return 1;
+return false;
 }
 
 close(fd);
@@ -201,14 +201,14 @@ static int QEMU_Elf_map(QEMU_Elf *qe, const char 
*filename)
 if (gerr) {
 eprintf("Failed to map ELF dump file \'%s\'\n", filename);
 g_error_free(gerr);
-return 1;
+return false;
 }
 
 qe->map = g_mapped_file_get_contents(qe->gmf);
 qe->size = g_mapped_file_get_length(qe->gmf);
 #endif
 
-return 0;
+return true;
 }
 
 static void QEMU_Elf_unmap(QEMU_Elf *qe)
@@ -220,25 +220,25 @@ static void QEMU_Elf_unmap(QEMU_Elf *qe)
 #endif
 }
 
-int QEMU_Elf_init(QEMU_Elf *qe, const char *filename)
+bool QEMU_Elf_init(QEMU_Elf *qe, const char *filename)
 {
-if (QEMU_Elf_map(qe, filename)) {
-return 1;
+if (!QEMU_Elf_map(qe, filename)) {
+return false;
 }
 
 if (!check_ehdr(qe)) {
 eprintf("Input file has the wrong format\n");
 QEMU_Elf_unmap(qe);
-return 1;
+return false;
 }
 
-if (init_states(qe)) {
+if (!init_states(qe)) {
 eprintf("Failed to extract QEMU CPU states\n");
 QEMU_Elf_unmap(qe);
-return 1;
+return false;
 }
 
-return 0;
+return true;
 }
 
 void QEMU_Elf_exit(QEMU_Elf *qe)

-- 
2.44.0




[PATCH v3 07/19] contrib/elf2dmp: Fix error reporting style in pdb.c

2024-03-05 Thread Akihiko Odaki
include/qapi/error.h says:
> We recommend
> * bool-valued functions return true on success / false on failure,
> ...

Signed-off-by: Akihiko Odaki 
---
 contrib/elf2dmp/pdb.h  |  2 +-
 contrib/elf2dmp/main.c |  2 +-
 contrib/elf2dmp/pdb.c  | 50 +-
 3 files changed, 27 insertions(+), 27 deletions(-)

diff --git a/contrib/elf2dmp/pdb.h b/contrib/elf2dmp/pdb.h
index 2a50da56ac96..feddf1862f08 100644
--- a/contrib/elf2dmp/pdb.h
+++ b/contrib/elf2dmp/pdb.h
@@ -233,7 +233,7 @@ struct pdb_reader {
 size_t segs_size;
 };
 
-int pdb_init_from_file(const char *name, struct pdb_reader *reader);
+bool pdb_init_from_file(const char *name, struct pdb_reader *reader);
 void pdb_exit(struct pdb_reader *reader);
 uint64_t pdb_resolve(uint64_t img_base, struct pdb_reader *r, const char 
*name);
 uint64_t pdb_find_public_v3_symbol(struct pdb_reader *reader, const char 
*name);
diff --git a/contrib/elf2dmp/main.c b/contrib/elf2dmp/main.c
index d295fd92be2f..7a3a7225905e 100644
--- a/contrib/elf2dmp/main.c
+++ b/contrib/elf2dmp/main.c
@@ -596,7 +596,7 @@ int main(int argc, char *argv[])
 goto out_ps;
 }
 
-if (pdb_init_from_file(PDB_NAME, )) {
+if (!pdb_init_from_file(PDB_NAME, )) {
 eprintf("Failed to initialize PDB reader\n");
 goto out_pdb_file;
 }
diff --git a/contrib/elf2dmp/pdb.c b/contrib/elf2dmp/pdb.c
index abf17c2e7c12..1c5051425185 100644
--- a/contrib/elf2dmp/pdb.c
+++ b/contrib/elf2dmp/pdb.c
@@ -158,30 +158,30 @@ static void *pdb_ds_read_file(struct pdb_reader* r, 
uint32_t file_number)
 return pdb_ds_read(r->ds.header, block_list, file_size[file_number]);
 }
 
-static int pdb_init_segments(struct pdb_reader *r)
+static bool pdb_init_segments(struct pdb_reader *r)
 {
 unsigned stream_idx = r->segments;
 
 r->segs = pdb_ds_read_file(r, stream_idx);
 if (!r->segs) {
-return 1;
+return false;
 }
 
 r->segs_size = pdb_get_file_size(r, stream_idx);
 if (!r->segs_size) {
-return 1;
+return false;
 }
 
-return 0;
+return true;
 }
 
-static int pdb_init_symbols(struct pdb_reader *r)
+static bool pdb_init_symbols(struct pdb_reader *r)
 {
 PDB_SYMBOLS *symbols;
 
 symbols = pdb_ds_read_file(r, 3);
 if (!symbols) {
-return 1;
+return false;
 }
 
 r->symbols = symbols;
@@ -198,18 +198,18 @@ static int pdb_init_symbols(struct pdb_reader *r)
 goto out_symbols;
 }
 
-return 0;
+return true;
 
 out_symbols:
 g_free(symbols);
 
-return 1;
+return false;
 }
 
-static int pdb_reader_ds_init(struct pdb_reader *r, PDB_DS_HEADER *hdr)
+static bool pdb_reader_ds_init(struct pdb_reader *r, PDB_DS_HEADER *hdr)
 {
 if (hdr->block_size == 0) {
-return 1;
+return false;
 }
 
 memset(r->file_used, 0, sizeof(r->file_used));
@@ -218,22 +218,22 @@ static int pdb_reader_ds_init(struct pdb_reader *r, 
PDB_DS_HEADER *hdr)
 hdr->toc_page * hdr->block_size), hdr->toc_size);
 
 if (!r->ds.toc) {
-return 1;
+return false;
 }
 
-return 0;
+return true;
 }
 
-static int pdb_reader_init(struct pdb_reader *r, void *data)
+static bool pdb_reader_init(struct pdb_reader *r, void *data)
 {
 const char pdb7[] = "Microsoft C/C++ MSF 7.00";
 
 if (memcmp(data, pdb7, sizeof(pdb7) - 1)) {
-return 1;
+return false;
 }
 
-if (pdb_reader_ds_init(r, data)) {
-return 1;
+if (!pdb_reader_ds_init(r, data)) {
+return false;
 }
 
 r->ds.root = pdb_ds_read_file(r, 1);
@@ -241,15 +241,15 @@ static int pdb_reader_init(struct pdb_reader *r, void 
*data)
 goto out_ds;
 }
 
-if (pdb_init_symbols(r)) {
+if (!pdb_init_symbols(r)) {
 goto out_root;
 }
 
-if (pdb_init_segments(r)) {
+if (!pdb_init_segments(r)) {
 goto out_sym;
 }
 
-return 0;
+return true;
 
 out_sym:
 pdb_exit_symbols(r);
@@ -258,7 +258,7 @@ out_root:
 out_ds:
 pdb_reader_ds_exit(r);
 
-return 1;
+return false;
 }
 
 static void pdb_reader_exit(struct pdb_reader *r)
@@ -269,7 +269,7 @@ static void pdb_reader_exit(struct pdb_reader *r)
 pdb_reader_ds_exit(r);
 }
 
-int pdb_init_from_file(const char *name, struct pdb_reader *reader)
+bool pdb_init_from_file(const char *name, struct pdb_reader *reader)
 {
 GError *gerr = NULL;
 void *map;
@@ -278,21 +278,21 @@ int pdb_init_from_file(const char *name, struct 
pdb_reader *reader)
 if (gerr) {
 eprintf("Failed to map PDB file \'%s\'\n", name);
 g_error_free(gerr);
-return 1;
+return false;
 }
 
 reader->file_size = g_mapped_file_get_length(reader->gmf);
 map = g_mapped_file_get_contents(reader->gmf);
-if (pdb_reader_init(reader, map)) {
+if (!pdb_reader_init(reader, map)) {
 goto out_unmap;
 }
 
-return 0;
+return true;
 
 out_unmap:
 

[PATCH v3 00/19] contrib/elf2dmp: Improve robustness

2024-03-05 Thread Akihiko Odaki
elf2dmp sometimes fails to work with partially corrupted dumps, and also
emits warnings when sanitizers are in use. This series are collections
of changes to improve the situation.

Signed-off-by: Akihiko Odaki 
---
Changes in v3:
- Split patch "contrib/elf2dmp: Conform to the error reporting pattern".
  (Peter Maydell)
- Stated that the relevant value is little-endian in patch
  "contrib/elf2dmp: Use lduw_le_p() to read PDB".
- Added a message saying "Build it only for little endian hosts until
  they are fixed." for patch "contrib/elf2dmp: Build only for little
  endian host".
- Added patch "contrib/elf2dmp: Ensure phdrs fit in file" to fix
  https://gitlab.com/qemu-project/qemu/-/issues/2202 as patch
  "contrib/elf2dmp: Clamp QEMU note to file size" was not really fixing
  the crash.
- Link to v2: 
https://lore.kernel.org/r/20240305-elf2dmp-v2-0-86ff2163a...@daynix.com

Changes in v2:
- Added patch "contrib/elf2dmp: Remove unnecessary err flags".
- Added patch "contrib/elf2dmp: Assume error by default".
- Added patch "contrib/elf2dmp: Conform to the error reporting pattern".
- Added patch "contrib/elf2dmp: Build only for little endian host".
- Added patch "contrib/elf2dmp: Use GPtrArray".
- Added patch "contrib/elf2dmp: Clamp QEMU note to file size".
- Changed error handling in patch "contrib/elf2dmp: Ensure segment fits
  in file" (Peter Maydell)
- Added a comment to fill_context() that it continues on failure.
  (Peter Maydell)
- Link to v1: 
https://lore.kernel.org/r/20240303-elf2dmp-v1-0-bea6649fe...@daynix.com

---
Akihiko Odaki (19):
  contrib/elf2dmp: Remove unnecessary err flags
  contrib/elf2dmp: Assume error by default
  contrib/elf2dmp: Continue even contexts are lacking
  contrib/elf2dmp: Change pa_space_create() signature
  contrib/elf2dmp: Fix error reporting style in addrspace.c
  contrib/elf2dmp: Fix error reporting style in download.c
  contrib/elf2dmp: Fix error reporting style in pdb.c
  contrib/elf2dmp: Fix error reporting style in qemu_elf.c
  contrib/elf2dmp: Fix error reporting style in main.c
  contrib/elf2dmp: Always check for PA resolution failure
  contrib/elf2dmp: Always destroy PA space
  contrib/elf2dmp: Ensure segment fits in file
  contrib/elf2dmp: Use lduw_le_p() to read PDB
  contrib/elf2dmp: Use rol64() to decode
  MAINTAINERS: Add Akihiko Odaki as a elf2dmp reviewer
  contrib/elf2dmp: Build only for little endian host
  contrib/elf2dmp: Use GPtrArray
  contrib/elf2dmp: Clamp QEMU note to file size
  contrib/elf2dmp: Ensure phdrs fit in file

 MAINTAINERS |   1 +
 contrib/elf2dmp/addrspace.h |   6 +-
 contrib/elf2dmp/download.h  |   2 +-
 contrib/elf2dmp/pdb.h   |   2 +-
 contrib/elf2dmp/qemu_elf.h  |   2 +-
 contrib/elf2dmp/addrspace.c |  63 ++---
 contrib/elf2dmp/download.c  |  12 ++--
 contrib/elf2dmp/main.c  | 168 
 contrib/elf2dmp/pdb.c   |  61 +++-
 contrib/elf2dmp/qemu_elf.c  | 150 ++-
 contrib/elf2dmp/meson.build |   2 +-
 11 files changed, 238 insertions(+), 231 deletions(-)
---
base-commit: bfe8020c814a30479a4241aaa78b63960655962b
change-id: 20240301-elf2dmp-1a6a551f8663

Best regards,
-- 
Akihiko Odaki 




[PATCH v3 11/19] contrib/elf2dmp: Always destroy PA space

2024-03-05 Thread Akihiko Odaki
Destroy PA space even if paging base couldn't be found, fixing memory
leak.

Signed-off-by: Akihiko Odaki 
Reviewed-by: Peter Maydell 
---
 contrib/elf2dmp/main.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/contrib/elf2dmp/main.c b/contrib/elf2dmp/main.c
index c290781feb18..51e1abe26a17 100644
--- a/contrib/elf2dmp/main.c
+++ b/contrib/elf2dmp/main.c
@@ -549,7 +549,7 @@ int main(int argc, char *argv[])
 va_space_create(, , state->cr[3]);
 if (!fix_dtb(, _elf)) {
 eprintf("Failed to find paging base\n");
-goto out_elf;
+goto out_ps;
 }
 
 printf("CPU #0 IDT is at 0x%016"PRIx64"\n", state->idt.base);
@@ -634,7 +634,6 @@ out_pdb_file:
 unlink(PDB_NAME);
 out_ps:
 pa_space_destroy();
-out_elf:
 QEMU_Elf_exit(_elf);
 
 return err;

-- 
2.44.0




[PATCH v3 10/19] contrib/elf2dmp: Always check for PA resolution failure

2024-03-05 Thread Akihiko Odaki
Not checking PA resolution failure can result in NULL deference.

Signed-off-by: Akihiko Odaki 
Reviewed-by: Peter Maydell 
---
 contrib/elf2dmp/addrspace.c | 46 -
 1 file changed, 29 insertions(+), 17 deletions(-)

diff --git a/contrib/elf2dmp/addrspace.c b/contrib/elf2dmp/addrspace.c
index c995c723ae80..e01860d15b07 100644
--- a/contrib/elf2dmp/addrspace.c
+++ b/contrib/elf2dmp/addrspace.c
@@ -22,7 +22,7 @@ static struct pa_block *pa_space_find_block(struct pa_space 
*ps, uint64_t pa)
 return NULL;
 }
 
-static uint8_t *pa_space_resolve(struct pa_space *ps, uint64_t pa)
+static void *pa_space_resolve(struct pa_space *ps, uint64_t pa)
 {
 struct pa_block *block = pa_space_find_block(ps, pa);
 
@@ -33,6 +33,19 @@ static uint8_t *pa_space_resolve(struct pa_space *ps, 
uint64_t pa)
 return block->addr + (pa - block->paddr);
 }
 
+static bool pa_space_read64(struct pa_space *ps, uint64_t pa, uint64_t *value)
+{
+uint64_t *resolved = pa_space_resolve(ps, pa);
+
+if (!resolved) {
+return false;
+}
+
+*value = *resolved;
+
+return true;
+}
+
 static void pa_block_align(struct pa_block *b)
 {
 uint64_t low_align = ((b->paddr - 1) | ELF2DMP_PAGE_MASK) + 1 - b->paddr;
@@ -106,19 +119,20 @@ void va_space_create(struct va_space *vs, struct pa_space 
*ps, uint64_t dtb)
 va_space_set_dtb(vs, dtb);
 }
 
-static uint64_t get_pml4e(struct va_space *vs, uint64_t va)
+static bool get_pml4e(struct va_space *vs, uint64_t va, uint64_t *value)
 {
 uint64_t pa = (vs->dtb & 0xff000) | ((va & 0xff80) >> 36);
 
-return *(uint64_t *)pa_space_resolve(vs->ps, pa);
+return pa_space_read64(vs->ps, pa, value);
 }
 
-static uint64_t get_pdpi(struct va_space *vs, uint64_t va, uint64_t pml4e)
+static bool get_pdpi(struct va_space *vs, uint64_t va, uint64_t pml4e,
+uint64_t *value)
 {
 uint64_t pdpte_paddr = (pml4e & 0xff000) |
 ((va & 0x7FC000) >> 27);
 
-return *(uint64_t *)pa_space_resolve(vs->ps, pdpte_paddr);
+return pa_space_read64(vs->ps, pdpte_paddr, value);
 }
 
 static uint64_t pde_index(uint64_t va)
@@ -131,11 +145,12 @@ static uint64_t pdba_base(uint64_t pdpe)
 return pdpe & 0xFF000;
 }
 
-static uint64_t get_pgd(struct va_space *vs, uint64_t va, uint64_t pdpe)
+static bool get_pgd(struct va_space *vs, uint64_t va, uint64_t pdpe,
+   uint64_t *value)
 {
 uint64_t pgd_entry = pdba_base(pdpe) + pde_index(va) * 8;
 
-return *(uint64_t *)pa_space_resolve(vs->ps, pgd_entry);
+return pa_space_read64(vs->ps, pgd_entry, value);
 }
 
 static uint64_t pte_index(uint64_t va)
@@ -148,11 +163,12 @@ static uint64_t ptba_base(uint64_t pde)
 return pde & 0xFF000;
 }
 
-static uint64_t get_pte(struct va_space *vs, uint64_t va, uint64_t pgd)
+static bool get_pte(struct va_space *vs, uint64_t va, uint64_t pgd,
+   uint64_t *value)
 {
 uint64_t pgd_val = ptba_base(pgd) + pte_index(va) * 8;
 
-return *(uint64_t *)pa_space_resolve(vs->ps, pgd_val);
+return pa_space_read64(vs->ps, pgd_val, value);
 }
 
 static uint64_t get_paddr(uint64_t va, uint64_t pte)
@@ -184,13 +200,11 @@ static uint64_t va_space_va2pa(struct va_space *vs, 
uint64_t va)
 {
 uint64_t pml4e, pdpe, pgd, pte;
 
-pml4e = get_pml4e(vs, va);
-if (!is_present(pml4e)) {
+if (!get_pml4e(vs, va, ) || !is_present(pml4e)) {
 return INVALID_PA;
 }
 
-pdpe = get_pdpi(vs, va, pml4e);
-if (!is_present(pdpe)) {
+if (!get_pdpi(vs, va, pml4e, ) || !is_present(pdpe)) {
 return INVALID_PA;
 }
 
@@ -198,8 +212,7 @@ static uint64_t va_space_va2pa(struct va_space *vs, 
uint64_t va)
 return get_1GB_paddr(va, pdpe);
 }
 
-pgd = get_pgd(vs, va, pdpe);
-if (!is_present(pgd)) {
+if (!get_pgd(vs, va, pdpe, ) || !is_present(pgd)) {
 return INVALID_PA;
 }
 
@@ -207,8 +220,7 @@ static uint64_t va_space_va2pa(struct va_space *vs, 
uint64_t va)
 return get_2MB_paddr(va, pgd);
 }
 
-pte = get_pte(vs, va, pgd);
-if (!is_present(pte)) {
+if (!get_pte(vs, va, pgd, ) || !is_present(pte)) {
 return INVALID_PA;
 }
 

-- 
2.44.0




Re: [PATCH] hw/core/machine-smp: Remove deprecated "parameter=0" SMP configurations

2024-03-05 Thread Zhao Liu
On Wed, Mar 06, 2024 at 10:19:41AM +0530, Prasad Pandit wrote:
> Date: Wed, 6 Mar 2024 10:19:41 +0530
> From: Prasad Pandit 
> Subject: Re: [PATCH] hw/core/machine-smp: Remove deprecated "parameter=0"
>  SMP configurations
> 
> Hello Zhao,
> 
> On Wed, 6 Mar 2024 at 08:49, Zhao Liu  wrote:
> >> then checking 'config->has_maxcpus ?' above is probably not required I
> >> think. It could just be
> >>
> >>maxcpus = config->maxcpus
> >
> > Yes.
> >
> > > If a user does not specify config->maxcpus with -smp option, then it
> > > could default to zero(0) in 'config' parameter? (same for other config
> > > fields)
> >
> > Yes. I could post another series for this cleanup soon.
> > The above change you suggested doesn't require API changes ;-).
> 
> * Great!  (Communication is the most difficult skill to master. :))
> 
> * If you plan to send a separate patch for above refactoring, then I'd
> add Reviewed-by for this one.
 
Yeah, I will send a series, which will also include this patch, to avoid
trivial smp cleanup fragmentation.

> Reviewed-by: Prasad Pandit 

Thanks!

-Zhao




[PATCH v3 19/19] contrib/elf2dmp: Ensure phdrs fit in file

2024-03-05 Thread Akihiko Odaki
Callers of elf64_getphdr() and elf_getphdrnum() assume phdrs are
accessible.

Resolves: https://gitlab.com/qemu-project/qemu/-/issues/2202
Signed-off-by: Akihiko Odaki 
---
 contrib/elf2dmp/qemu_elf.c | 8 
 1 file changed, 8 insertions(+)

diff --git a/contrib/elf2dmp/qemu_elf.c b/contrib/elf2dmp/qemu_elf.c
index 8d750adf904a..c9bad6e82cf3 100644
--- a/contrib/elf2dmp/qemu_elf.c
+++ b/contrib/elf2dmp/qemu_elf.c
@@ -132,6 +132,7 @@ static void exit_states(QEMU_Elf *qe)
 static bool check_ehdr(QEMU_Elf *qe)
 {
 Elf64_Ehdr *ehdr = qe->map;
+uint64_t phendoff;
 
 if (sizeof(Elf64_Ehdr) > qe->size) {
 eprintf("Invalid input dump file size\n");
@@ -173,6 +174,13 @@ static bool check_ehdr(QEMU_Elf *qe)
 return false;
 }
 
+if (umul64_overflow(ehdr->e_phnum, sizeof(Elf64_Phdr), ) ||
+uadd64_overflow(phendoff, ehdr->e_phoff, ) ||
+phendoff > qe->size) {
+eprintf("phdrs do not fit in file\n");
+return false;
+}
+
 return true;
 }
 

-- 
2.44.0




[PATCH v3 09/19] contrib/elf2dmp: Fix error reporting style in main.c

2024-03-05 Thread Akihiko Odaki
include/qapi/error.h says:
> We recommend
> * bool-valued functions return true on success / false on failure,
> ...

Signed-off-by: Akihiko Odaki 
---
 contrib/elf2dmp/main.c | 63 +-
 1 file changed, 32 insertions(+), 31 deletions(-)

diff --git a/contrib/elf2dmp/main.c b/contrib/elf2dmp/main.c
index cb28971789e4..c290781feb18 100644
--- a/contrib/elf2dmp/main.c
+++ b/contrib/elf2dmp/main.c
@@ -186,13 +186,13 @@ static void 
win_context_init_from_qemu_cpu_state(WinContext64 *ctx,
  * Finds paging-structure hierarchy base,
  * if previously set doesn't give access to kernel structures
  */
-static int fix_dtb(struct va_space *vs, QEMU_Elf *qe)
+static bool fix_dtb(struct va_space *vs, QEMU_Elf *qe)
 {
 /*
  * Firstly, test previously set DTB.
  */
 if (va_space_resolve(vs, SharedUserData)) {
-return 0;
+return true;
 }
 
 /*
@@ -206,7 +206,7 @@ static int fix_dtb(struct va_space *vs, QEMU_Elf *qe)
 va_space_set_dtb(vs, s->cr[3]);
 printf("DTB 0x%016"PRIx64" has been found from CPU #%zu"
 " as system task CR3\n", vs->dtb, i);
-return !(va_space_resolve(vs, SharedUserData));
+return !!(va_space_resolve(vs, SharedUserData));
 }
 }
 
@@ -220,16 +220,16 @@ static int fix_dtb(struct va_space *vs, QEMU_Elf *qe)
 uint64_t *cr3 = va_space_resolve(vs, Prcb + 0x7000);
 
 if (!cr3) {
-return 1;
+return false;
 }
 
 va_space_set_dtb(vs, *cr3);
 printf("DirectoryTableBase = 0x%016"PRIx64" has been found from CPU #0"
 " as interrupt handling CR3\n", vs->dtb);
-return !(va_space_resolve(vs, SharedUserData));
+return !!(va_space_resolve(vs, SharedUserData));
 }
 
-return 1;
+return true;
 }
 
 static void try_merge_runs(struct pa_space *ps,
@@ -268,9 +268,10 @@ static void try_merge_runs(struct pa_space *ps,
 }
 }
 
-static int fill_header(WinDumpHeader64 *hdr, struct pa_space *ps,
-struct va_space *vs, uint64_t KdDebuggerDataBlock,
-KDDEBUGGER_DATA64 *kdbg, uint64_t KdVersionBlock, int nr_cpus)
+static bool fill_header(WinDumpHeader64 *hdr, struct pa_space *ps,
+struct va_space *vs, uint64_t KdDebuggerDataBlock,
+KDDEBUGGER_DATA64 *kdbg, uint64_t KdVersionBlock,
+int nr_cpus)
 {
 uint32_t *suite_mask = va_space_resolve(vs, SharedUserData +
 KUSD_OFFSET_SUITE_MASK);
@@ -283,12 +284,12 @@ static int fill_header(WinDumpHeader64 *hdr, struct 
pa_space *ps,
 QEMU_BUILD_BUG_ON(KUSD_OFFSET_PRODUCT_TYPE >= ELF2DMP_PAGE_SIZE);
 
 if (!suite_mask || !product_type) {
-return 1;
+return false;
 }
 
 if (!va_space_rw(vs, KdVersionBlock, , sizeof(kvb), 0)) {
 eprintf("Failed to extract KdVersionBlock\n");
-return 1;
+return false;
 }
 
 h = (WinDumpHeader64) {
@@ -333,7 +334,7 @@ static int fill_header(WinDumpHeader64 *hdr, struct 
pa_space *ps,
 
 *hdr = h;
 
-return 0;
+return true;
 }
 
 /*
@@ -379,8 +380,8 @@ static void fill_context(KDDEBUGGER_DATA64 *kdbg,
 }
 }
 
-static int pe_get_data_dir_entry(uint64_t base, void *start_addr, int idx,
-void *entry, size_t size, struct va_space *vs)
+static bool pe_get_data_dir_entry(uint64_t base, void *start_addr, int idx,
+  void *entry, size_t size, struct va_space 
*vs)
 {
 const char e_magic[2] = "MZ";
 const char Signature[4] = "PE\0\0";
@@ -393,38 +394,38 @@ static int pe_get_data_dir_entry(uint64_t base, void 
*start_addr, int idx,
 QEMU_BUILD_BUG_ON(sizeof(*dos_hdr) >= ELF2DMP_PAGE_SIZE);
 
 if (memcmp(_hdr->e_magic, e_magic, sizeof(e_magic))) {
-return 1;
+return false;
 }
 
 if (!va_space_rw(vs, base + dos_hdr->e_lfanew,
  _hdrs, sizeof(nt_hdrs), 0)) {
-return 1;
+return false;
 }
 
 if (memcmp(_hdrs.Signature, Signature, sizeof(Signature)) ||
 file_hdr->Machine != 0x8664 || opt_hdr->Magic != 0x020b) {
-return 1;
+return false;
 }
 
 if (!va_space_rw(vs, base + data_dir[idx].VirtualAddress, entry, size, 0)) 
{
-return 1;
+return false;
 }
 
 printf("Data directory entry #%d: RVA = 0x%08"PRIx32"\n", idx,
 (uint32_t)data_dir[idx].VirtualAddress);
 
-return 0;
+return true;
 }
 
-static int write_dump(struct pa_space *ps,
-WinDumpHeader64 *hdr, const char *name)
+static bool write_dump(struct pa_space *ps,
+   WinDumpHeader64 *hdr, const char *name)
 {
 FILE *dmp_file = fopen(name, "wb");
 size_t i;
 
 if (!dmp_file) {
 eprintf("Failed to open output file \'%s\'\n", name);
-return 1;
+return false;
 }
 
 printf("Writing header to file...\n");
@@ -432,7 

[PATCH v3 16/19] contrib/elf2dmp: Build only for little endian host

2024-03-05 Thread Akihiko Odaki
elf2dmp assumes little endian host in many places. Build it only for
little endian hosts until they are fixed.

Signed-off-by: Akihiko Odaki 
---
 contrib/elf2dmp/meson.build | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/contrib/elf2dmp/meson.build b/contrib/elf2dmp/meson.build
index 6707d43c4fa5..046569861f7a 100644
--- a/contrib/elf2dmp/meson.build
+++ b/contrib/elf2dmp/meson.build
@@ -1,4 +1,4 @@
-if curl.found()
+if curl.found() and host_machine.endian() == 'little'
   executable('elf2dmp', files('main.c', 'addrspace.c', 'download.c', 'pdb.c', 
'qemu_elf.c'), genh,
  dependencies: [glib, curl],
  install: true)

-- 
2.44.0




[PATCH v3 15/19] MAINTAINERS: Add Akihiko Odaki as a elf2dmp reviewer

2024-03-05 Thread Akihiko Odaki
Signed-off-by: Akihiko Odaki 
Reviewed-by: Peter Maydell 
---
 MAINTAINERS | 1 +
 1 file changed, 1 insertion(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index 65dfdc9677e4..d25403f3709b 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -3583,6 +3583,7 @@ F: util/iova-tree.c
 
 elf2dmp
 M: Viktor Prutyanov 
+R: Akihiko Odaki 
 S: Maintained
 F: contrib/elf2dmp/
 

-- 
2.44.0




[PATCH v3 12/19] contrib/elf2dmp: Ensure segment fits in file

2024-03-05 Thread Akihiko Odaki
This makes elf2dmp more robust against corrupted inputs.

Signed-off-by: Akihiko Odaki 
Reviewed-by: Peter Maydell 
---
 contrib/elf2dmp/addrspace.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/contrib/elf2dmp/addrspace.c b/contrib/elf2dmp/addrspace.c
index e01860d15b07..81295a11534a 100644
--- a/contrib/elf2dmp/addrspace.c
+++ b/contrib/elf2dmp/addrspace.c
@@ -88,11 +88,12 @@ void pa_space_create(struct pa_space *ps, QEMU_Elf 
*qemu_elf)
 ps->block = g_new(struct pa_block, ps->block_nr);
 
 for (i = 0; i < phdr_nr; i++) {
-if (phdr[i].p_type == PT_LOAD) {
+if (phdr[i].p_type == PT_LOAD && phdr[i].p_offset < qemu_elf->size) {
 ps->block[block_i] = (struct pa_block) {
 .addr = (uint8_t *)qemu_elf->map + phdr[i].p_offset,
 .paddr = phdr[i].p_paddr,
-.size = phdr[i].p_filesz,
+.size = MIN(phdr[i].p_filesz,
+qemu_elf->size - phdr[i].p_offset),
 };
 pa_block_align(>block[block_i]);
 block_i = ps->block[block_i].size ? (block_i + 1) : block_i;

-- 
2.44.0




[PATCH v3 14/19] contrib/elf2dmp: Use rol64() to decode

2024-03-05 Thread Akihiko Odaki
rol64() is roubust against too large shift values and fixes UBSan
warnings.

Signed-off-by: Akihiko Odaki 
Reviewed-by: Peter Maydell 
---
 contrib/elf2dmp/main.c | 8 ++--
 1 file changed, 2 insertions(+), 6 deletions(-)

diff --git a/contrib/elf2dmp/main.c b/contrib/elf2dmp/main.c
index 51e1abe26a17..e404612bec00 100644
--- a/contrib/elf2dmp/main.c
+++ b/contrib/elf2dmp/main.c
@@ -6,6 +6,7 @@
  */
 
 #include "qemu/osdep.h"
+#include "qemu/bitops.h"
 
 #include "err.h"
 #include "addrspace.h"
@@ -47,11 +48,6 @@ static const uint64_t SharedUserData = 0xf780;
 s ? printf(#s" = 0x%016"PRIx64"\n", s) :\
 eprintf("Failed to resolve "#s"\n"), s)
 
-static uint64_t rol(uint64_t x, uint64_t y)
-{
-return (x << y) | (x >> (64 - y));
-}
-
 /*
  * Decoding algorithm can be found in Volatility project
  */
@@ -64,7 +60,7 @@ static void kdbg_decode(uint64_t *dst, uint64_t *src, size_t 
size,
 uint64_t block;
 
 block = src[i];
-block = rol(block ^ kwn, (uint8_t)kwn);
+block = rol64(block ^ kwn, kwn);
 block = __builtin_bswap64(block ^ kdbe) ^ kwa;
 dst[i] = block;
 }

-- 
2.44.0




[PATCH v3 05/19] contrib/elf2dmp: Fix error reporting style in addrspace.c

2024-03-05 Thread Akihiko Odaki
include/qapi/error.h says:
> We recommend
> * bool-valued functions return true on success / false on failure,
> ...

Signed-off-by: Akihiko Odaki 
---
 contrib/elf2dmp/addrspace.h |  4 ++--
 contrib/elf2dmp/addrspace.c |  8 
 contrib/elf2dmp/main.c  | 47 +
 3 files changed, 28 insertions(+), 31 deletions(-)

diff --git a/contrib/elf2dmp/addrspace.h b/contrib/elf2dmp/addrspace.h
index c868d6473873..2ad30a9da48a 100644
--- a/contrib/elf2dmp/addrspace.h
+++ b/contrib/elf2dmp/addrspace.h
@@ -39,7 +39,7 @@ void pa_space_destroy(struct pa_space *ps);
 void va_space_create(struct va_space *vs, struct pa_space *ps, uint64_t dtb);
 void va_space_set_dtb(struct va_space *vs, uint64_t dtb);
 void *va_space_resolve(struct va_space *vs, uint64_t va);
-int va_space_rw(struct va_space *vs, uint64_t addr,
-void *buf, size_t size, int is_write);
+bool va_space_rw(struct va_space *vs, uint64_t addr,
+ void *buf, size_t size, int is_write);
 
 #endif /* ADDRSPACE_H */
diff --git a/contrib/elf2dmp/addrspace.c b/contrib/elf2dmp/addrspace.c
index 4c127c9b1ec4..c995c723ae80 100644
--- a/contrib/elf2dmp/addrspace.c
+++ b/contrib/elf2dmp/addrspace.c
@@ -226,8 +226,8 @@ void *va_space_resolve(struct va_space *vs, uint64_t va)
 return pa_space_resolve(vs->ps, pa);
 }
 
-int va_space_rw(struct va_space *vs, uint64_t addr,
-void *buf, size_t size, int is_write)
+bool va_space_rw(struct va_space *vs, uint64_t addr,
+ void *buf, size_t size, int is_write)
 {
 while (size) {
 uint64_t page = addr & ELF2DMP_PFN_MASK;
@@ -238,7 +238,7 @@ int va_space_rw(struct va_space *vs, uint64_t addr,
 
 ptr = va_space_resolve(vs, addr);
 if (!ptr) {
-return 1;
+return false;
 }
 
 if (is_write) {
@@ -252,5 +252,5 @@ int va_space_rw(struct va_space *vs, uint64_t addr,
 addr += s;
 }
 
-return 0;
+return true;
 }
diff --git a/contrib/elf2dmp/main.c b/contrib/elf2dmp/main.c
index 8a71e2efd281..09af39422f1e 100644
--- a/contrib/elf2dmp/main.c
+++ b/contrib/elf2dmp/main.c
@@ -79,9 +79,9 @@ static KDDEBUGGER_DATA64 *get_kdbg(uint64_t KernBase, struct 
pdb_reader *pdb,
 bool decode = false;
 uint64_t kwn, kwa, KdpDataBlockEncoded;
 
-if (va_space_rw(vs,
-KdDebuggerDataBlock + offsetof(KDDEBUGGER_DATA64, Header),
-_hdr, sizeof(kdbg_hdr), 0)) {
+if (!va_space_rw(vs,
+ KdDebuggerDataBlock + offsetof(KDDEBUGGER_DATA64, Header),
+ _hdr, sizeof(kdbg_hdr), 0)) {
 eprintf("Failed to extract KDBG header\n");
 return NULL;
 }
@@ -97,8 +97,8 @@ static KDDEBUGGER_DATA64 *get_kdbg(uint64_t KernBase, struct 
pdb_reader *pdb,
 return NULL;
 }
 
-if (va_space_rw(vs, KiWaitNever, , sizeof(kwn), 0) ||
-va_space_rw(vs, KiWaitAlways, , sizeof(kwa), 0)) {
+if (!va_space_rw(vs, KiWaitNever, , sizeof(kwn), 0) ||
+!va_space_rw(vs, KiWaitAlways, , sizeof(kwa), 0)) {
 return NULL;
 }
 
@@ -122,7 +122,7 @@ static KDDEBUGGER_DATA64 *get_kdbg(uint64_t KernBase, 
struct pdb_reader *pdb,
 
 kdbg = g_malloc(kdbg_hdr.Size);
 
-if (va_space_rw(vs, KdDebuggerDataBlock, kdbg, kdbg_hdr.Size, 0)) {
+if (!va_space_rw(vs, KdDebuggerDataBlock, kdbg, kdbg_hdr.Size, 0)) {
 eprintf("Failed to extract entire KDBG\n");
 g_free(kdbg);
 return NULL;
@@ -286,7 +286,7 @@ static int fill_header(WinDumpHeader64 *hdr, struct 
pa_space *ps,
 return 1;
 }
 
-if (va_space_rw(vs, KdVersionBlock, , sizeof(kvb), 0)) {
+if (!va_space_rw(vs, KdVersionBlock, , sizeof(kvb), 0)) {
 eprintf("Failed to extract KdVersionBlock\n");
 return 1;
 }
@@ -352,8 +352,8 @@ static void fill_context(KDDEBUGGER_DATA64 *kdbg,
 WinContext64 ctx;
 QEMUCPUState *s = qe->state[i];
 
-if (va_space_rw(vs, kdbg->KiProcessorBlock + sizeof(Prcb) * i,
-, sizeof(Prcb), 0)) {
+if (!va_space_rw(vs, kdbg->KiProcessorBlock + sizeof(Prcb) * i,
+ , sizeof(Prcb), 0)) {
 eprintf("Failed to read CPU #%d PRCB location\n", i);
 continue;
 }
@@ -363,8 +363,8 @@ static void fill_context(KDDEBUGGER_DATA64 *kdbg,
 continue;
 }
 
-if (va_space_rw(vs, Prcb + kdbg->OffsetPrcbContext,
-, sizeof(Context), 0)) {
+if (!va_space_rw(vs, Prcb + kdbg->OffsetPrcbContext,
+ , sizeof(Context), 0)) {
 eprintf("Failed to read CPU #%d ContextFrame location\n", i);
 continue;
 }
@@ -372,7 +372,7 @@ static void fill_context(KDDEBUGGER_DATA64 *kdbg,
 printf("Filling context for CPU #%d...\n", i);
 win_context_init_from_qemu_cpu_state(, s);
 
-if (va_space_rw(vs, Context, , sizeof(ctx), 

[PATCH v3 02/19] contrib/elf2dmp: Assume error by default

2024-03-05 Thread Akihiko Odaki
A common construct in contrib/elf2dmp is to set "err" flag and goto
in error paths. In such a construct, there is only one successful path
while there are several error paths, so it will be more simpler to
initialize "err" flag set, and clear it in the successful path.

Signed-off-by: Akihiko Odaki 
Reviewed-by: Peter Maydell 
---
 contrib/elf2dmp/download.c |  4 +---
 contrib/elf2dmp/main.c | 15 +++
 2 files changed, 4 insertions(+), 15 deletions(-)

diff --git a/contrib/elf2dmp/download.c b/contrib/elf2dmp/download.c
index bd7650a7a27f..902dc04ffa5c 100644
--- a/contrib/elf2dmp/download.c
+++ b/contrib/elf2dmp/download.c
@@ -11,7 +11,7 @@
 
 int download_url(const char *name, const char *url)
 {
-int err = 0;
+int err = 1;
 FILE *file;
 CURL *curl = curl_easy_init();
 
@@ -21,7 +21,6 @@ int download_url(const char *name, const char *url)
 
 file = fopen(name, "wb");
 if (!file) {
-err = 1;
 goto out_curl;
 }
 
@@ -33,7 +32,6 @@ int download_url(const char *name, const char *url)
 || curl_easy_perform(curl) != CURLE_OK) {
 unlink(name);
 fclose(file);
-err = 1;
 } else {
 err = fclose(file);
 }
diff --git a/contrib/elf2dmp/main.c b/contrib/elf2dmp/main.c
index cbc38a7c103a..9b278f392e39 100644
--- a/contrib/elf2dmp/main.c
+++ b/contrib/elf2dmp/main.c
@@ -511,7 +511,7 @@ static void pe_get_pdb_symstore_hash(OMFSignatureRSDS 
*rsds, char *hash)
 
 int main(int argc, char *argv[])
 {
-int err = 0;
+int err = 1;
 QEMU_Elf qemu_elf;
 struct pa_space ps;
 struct va_space vs;
@@ -542,7 +542,6 @@ int main(int argc, char *argv[])
 
 if (pa_space_create(, _elf)) {
 eprintf("Failed to initialize physical address space\n");
-err = 1;
 goto out_elf;
 }
 
@@ -552,7 +551,6 @@ int main(int argc, char *argv[])
 va_space_create(, , state->cr[3]);
 if (fix_dtb(, _elf)) {
 eprintf("Failed to find paging base\n");
-err = 1;
 goto out_elf;
 }
 
@@ -561,7 +559,6 @@ int main(int argc, char *argv[])
 if (va_space_rw(, state->idt.base,
 _idt_desc, sizeof(first_idt_desc), 0)) {
 eprintf("Failed to get CPU #0 IDT[0]\n");
-err = 1;
 goto out_ps;
 }
 printf("CPU #0 IDT[0] -> 0x%016"PRIx64"\n", idt_desc_addr(first_idt_desc));
@@ -586,7 +583,6 @@ int main(int argc, char *argv[])
 
 if (!kernel_found) {
 eprintf("Failed to find NT kernel image\n");
-err = 1;
 goto out_ps;
 }
 
@@ -600,45 +596,40 @@ int main(int argc, char *argv[])
 
 if (download_url(PDB_NAME, pdb_url)) {
 eprintf("Failed to download PDB file\n");
-err = 1;
 goto out_ps;
 }
 
 if (pdb_init_from_file(PDB_NAME, )) {
 eprintf("Failed to initialize PDB reader\n");
-err = 1;
 goto out_pdb_file;
 }
 
 if (!SYM_RESOLVE(KernBase, , KdDebuggerDataBlock) ||
 !SYM_RESOLVE(KernBase, , KdVersionBlock)) {
-err = 1;
 goto out_pdb;
 }
 
 kdbg = get_kdbg(KernBase, , , KdDebuggerDataBlock);
 if (!kdbg) {
-err = 1;
 goto out_pdb;
 }
 
 if (fill_header(, , , KdDebuggerDataBlock, kdbg,
 KdVersionBlock, qemu_elf.state_nr)) {
-err = 1;
 goto out_kdbg;
 }
 
 if (fill_context(kdbg, , _elf)) {
-err = 1;
 goto out_kdbg;
 }
 
 if (write_dump(, , argv[2])) {
 eprintf("Failed to save dump\n");
-err = 1;
 goto out_kdbg;
 }
 
+err = 0;
+
 out_kdbg:
 g_free(kdbg);
 out_pdb:

-- 
2.44.0




[PATCH v3 01/19] contrib/elf2dmp: Remove unnecessary err flags

2024-03-05 Thread Akihiko Odaki
They are always evaluated to 1.

Signed-off-by: Akihiko Odaki 
Reviewed-by: Peter Maydell 
---
 contrib/elf2dmp/pdb.c | 14 +++---
 1 file changed, 3 insertions(+), 11 deletions(-)

diff --git a/contrib/elf2dmp/pdb.c b/contrib/elf2dmp/pdb.c
index 40991f5f4c34..abf17c2e7c12 100644
--- a/contrib/elf2dmp/pdb.c
+++ b/contrib/elf2dmp/pdb.c
@@ -177,7 +177,6 @@ static int pdb_init_segments(struct pdb_reader *r)
 
 static int pdb_init_symbols(struct pdb_reader *r)
 {
-int err = 0;
 PDB_SYMBOLS *symbols;
 
 symbols = pdb_ds_read_file(r, 3);
@@ -196,7 +195,6 @@ static int pdb_init_symbols(struct pdb_reader *r)
 /* Read global symbol table */
 r->modimage = pdb_ds_read_file(r, symbols->gsym_file);
 if (!r->modimage) {
-err = 1;
 goto out_symbols;
 }
 
@@ -205,7 +203,7 @@ static int pdb_init_symbols(struct pdb_reader *r)
 out_symbols:
 g_free(symbols);
 
-return err;
+return 1;
 }
 
 static int pdb_reader_ds_init(struct pdb_reader *r, PDB_DS_HEADER *hdr)
@@ -228,7 +226,6 @@ static int pdb_reader_ds_init(struct pdb_reader *r, 
PDB_DS_HEADER *hdr)
 
 static int pdb_reader_init(struct pdb_reader *r, void *data)
 {
-int err = 0;
 const char pdb7[] = "Microsoft C/C++ MSF 7.00";
 
 if (memcmp(data, pdb7, sizeof(pdb7) - 1)) {
@@ -241,17 +238,14 @@ static int pdb_reader_init(struct pdb_reader *r, void 
*data)
 
 r->ds.root = pdb_ds_read_file(r, 1);
 if (!r->ds.root) {
-err = 1;
 goto out_ds;
 }
 
 if (pdb_init_symbols(r)) {
-err = 1;
 goto out_root;
 }
 
 if (pdb_init_segments(r)) {
-err = 1;
 goto out_sym;
 }
 
@@ -264,7 +258,7 @@ out_root:
 out_ds:
 pdb_reader_ds_exit(r);
 
-return err;
+return 1;
 }
 
 static void pdb_reader_exit(struct pdb_reader *r)
@@ -278,7 +272,6 @@ static void pdb_reader_exit(struct pdb_reader *r)
 int pdb_init_from_file(const char *name, struct pdb_reader *reader)
 {
 GError *gerr = NULL;
-int err = 0;
 void *map;
 
 reader->gmf = g_mapped_file_new(name, TRUE, );
@@ -291,7 +284,6 @@ int pdb_init_from_file(const char *name, struct pdb_reader 
*reader)
 reader->file_size = g_mapped_file_get_length(reader->gmf);
 map = g_mapped_file_get_contents(reader->gmf);
 if (pdb_reader_init(reader, map)) {
-err = 1;
 goto out_unmap;
 }
 
@@ -300,7 +292,7 @@ int pdb_init_from_file(const char *name, struct pdb_reader 
*reader)
 out_unmap:
 g_mapped_file_unref(reader->gmf);
 
-return err;
+return 1;
 }
 
 void pdb_exit(struct pdb_reader *reader)

-- 
2.44.0




Re: What is the correct way to add linker dependency to QEMU build system?

2024-03-05 Thread Paz Offer
...after some testing...
[Trying to add 'libdl' to be linked with QEMU]

I did try to use 'g_module_open/close/symbol', but what I noticed is that 
'g_module_close' did not really unload my library.
So if I would do:

  1.  g_module_open(my-lib)
  2.  Load symbols, use my library...
  3.  g_module_close(my-lib)
  4.  Make modifications to my library and reload it:
  5.  g_module_open(my-lib)

Then the library was not really reloaded, and the old instance would still be 
used.

This did not happen when I used dlopen/dlclose.
Do we have a way to force 'g_module_close' to unload the library?

Thanks, Paz



From: Peter Maydell 
Sent: Thursday, February 29, 2024 7:34 PM
To: Paz Offer 
Cc: qemu-devel@nongnu.org 
Subject: Re: What is the correct way to add linker dependency to QEMU build 
system?

External email: Use caution opening links or attachments


On Thu, 29 Feb 2024 at 16:10, Paz Offer  wrote:
> I want to add library 'libdl' to be linked with QEMU build for a particular 
> target (e.g. - qemu-system-arm).
> Using meson I would typically do 'compiler.find_library(...)', and later add 
> the returned dependency to the binary dependencies list.
> However, in QEMU I understand that these configurations are done in the 
> './configure' file?
>
> What would be the correct way to do this?

If you can do the job using the glib g_module_open()/
g_module_symbol() functions (which is how QEMU itself does
loading of plugin and module DLLs, and which on Unix hosts
are pretty much wrappers around dlopen/dlsym) then you
don't need to link against libdl at all.

If this is for something you're planning to upstream
then it might be worth talking at a higher level about
what you're aiming to do. (If it's for something downstream
that you don't plan to ever upstream then you can do
whatever's easiest for you, of course.)

-- PMM


Re: [PATCH v1 0/8] virtio, vhost: Add VIRTIO_F_NOTIFICATION_DATA support

2024-03-05 Thread Jason Wang
On Tue, Mar 5, 2024 at 3:46 AM Jonah Palmer  wrote:
>
> The goal of these patches are to add support to a variety of virtio and
> vhost devices for the VIRTIO_F_NOTIFICATION_DATA transport feature. This
> feature indicates that a driver will pass extra data (instead of just a
> virtqueue's index) when notifying the corresponding device.
>
> The data passed in by the driver when this feature is enabled varies in
> format depending on if the device is using a split or packed virtqueue
> layout:
>
>  Split VQ
>   - Upper 16 bits: shadow_avail_idx
>   - Lower 16 bits: virtqueue index
>
>  Packed VQ
>   - Upper 16 bits: 1-bit wrap counter & 15-bit shadow_avail_idx
>   - Lower 16 bits: virtqueue index
>
> Also, due to the limitations of ioeventfd not being able to carry the
> extra provided by the driver, ioeventfd is left disabled for any devices
> using this feature.

Is there any method to overcome this? This might help for vhost.

Thanks

>
> A significant aspect of this effort has been to maintain compatibility
> across different backends. As such, the feature is offered by backend
> devices only when supported, with fallback mechanisms where backend
> support is absent.
>
> Jonah Palmer (8):
>   virtio/virtio-pci: Handle extra notification data
>   virtio-pci: Lock ioeventfd state with VIRTIO_F_NOTIFICATION_DATA
>   virtio-mmio: Handle extra notification data
>   virtio-mmio: Lock ioeventfd state with VIRTIO_F_NOTIFICATION_DATA
>   virtio-ccw: Handle extra notification data
>   virtio-ccw: Lock ioeventfd state with VIRTIO_F_NOTIFICATION_DATA
>   vhost/vhost-user: Add VIRTIO_F_NOTIFICATION_DATA to vhost feature bits
>   virtio: Add VIRTIO_F_NOTIFICATION_DATA property definition
>
>  hw/block/vhost-user-blk.c|  1 +
>  hw/net/vhost_net.c   |  2 ++
>  hw/s390x/s390-virtio-ccw.c   | 16 
>  hw/s390x/virtio-ccw.c|  6 --
>  hw/scsi/vhost-scsi.c |  1 +
>  hw/scsi/vhost-user-scsi.c|  1 +
>  hw/virtio/vhost-user-fs.c|  2 +-
>  hw/virtio/vhost-user-vsock.c |  1 +
>  hw/virtio/virtio-mmio.c  | 15 +++
>  hw/virtio/virtio-pci.c   | 16 +++-
>  hw/virtio/virtio.c   | 18 ++
>  include/hw/virtio/virtio.h   |  5 -
>  net/vhost-vdpa.c |  1 +
>  13 files changed, 68 insertions(+), 17 deletions(-)
>
> --
> 2.39.3
>




Re: [PATCH v2 2/2] e1000e: fix link state on resume

2024-03-05 Thread Jason Wang
Hi Laurent:

On Tue, Mar 5, 2024 at 6:07 PM Laurent Vivier  wrote:
>
> On 2/1/24 06:45, Jason Wang wrote:
> > On Wed, Jan 24, 2024 at 6:40 PM Laurent Vivier  wrote:
> >>
> >> On resume e1000e_vm_state_change() always calls e1000e_autoneg_resume()
> >> that sets link_down to false, and thus activates the link even
> >> if we have disabled it.
> >>
> >> The problem can be reproduced starting qemu in paused state (-S) and
> >> then set the link to down. When we resume the machine the link appears
> >> to be up.
> >>
> >> Reproducer:
> >>
> >> # qemu-system-x86_64 ... -device e1000e,netdev=netdev0,id=net0 -S
> >>
> >> {"execute": "qmp_capabilities" }
> >> {"execute": "set_link", "arguments": {"name": "net0", "up": false}}
> >> {"execute": "cont" }
> >>
> >> To fix the problem, merge the content of e1000e_vm_state_change()
> >> into e1000e_core_post_load() as e1000 does.
> >>
> >> Buglink: https://issues.redhat.com/browse/RHEL-21867
> >> Fixes: 6f3fbe4ed06a ("net: Introduce e1000e device emulation")
> >> Suggested-by: Akihiko Odaki 
> >> Signed-off-by: Laurent Vivier 
> >> ---
> >>
> >
> > I've queued this.
>
> Ping?

Plan to send a pull request with this by the end of this week.

Thanks

>
> Thanks,
> Laurent
>




Re: [PATCH v2 11/13] contrib/elf2dmp: Build only for little endian host

2024-03-05 Thread Akihiko Odaki

On 2024/03/05 22:33, Peter Maydell wrote:

On Tue, 5 Mar 2024 at 07:37, Akihiko Odaki  wrote:


elf2dmp assumes little endian host in many places.

Signed-off-by: Akihiko Odaki 
---
  contrib/elf2dmp/meson.build | 2 +-
  1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/contrib/elf2dmp/meson.build b/contrib/elf2dmp/meson.build
index 6707d43c4fa5..046569861f7a 100644
--- a/contrib/elf2dmp/meson.build
+++ b/contrib/elf2dmp/meson.build
@@ -1,4 +1,4 @@
-if curl.found()
+if curl.found() and host_machine.endian() == 'little'
executable('elf2dmp', files('main.c', 'addrspace.c', 'download.c', 'pdb.c', 
'qemu_elf.c'), genh,
   dependencies: [glib, curl],
   install: true)


If it assumes a little-endian host that is a bug and we
should fix it, not just disable building the tool on
big-endian systems.


I will accept if someone submits a proper fix in the future, but I'm not 
going to put effort on that. This is the best thing I can offer for now.


Regards,
Akihiko Odaki



Re: [PATCH v2 04/13] contrib/elf2dmp: Conform to the error reporting pattern

2024-03-05 Thread Akihiko Odaki

On 2024/03/05 22:28, Peter Maydell wrote:

On Tue, 5 Mar 2024 at 07:36, Akihiko Odaki  wrote:


include/qapi/error.h says:

We recommend
* bool-valued functions return true on success / false on failure,
...


Signed-off-by: Akihiko Odaki 
---
  contrib/elf2dmp/addrspace.h |   6 +--
  contrib/elf2dmp/download.h  |   2 +-
  contrib/elf2dmp/pdb.h   |   2 +-
  contrib/elf2dmp/qemu_elf.h  |   2 +-
  contrib/elf2dmp/addrspace.c |  12 ++---
  contrib/elf2dmp/download.c  |  10 ++--
  contrib/elf2dmp/main.c  | 114 +---
  contrib/elf2dmp/pdb.c   |  50 +--
  contrib/elf2dmp/qemu_elf.c  |  32 ++---
  9 files changed, 112 insertions(+), 118 deletions(-)


This is a bit big to review easily. Converting one function
(or a small set of closely related functions) at once would
make for an easier to review split.


I'll split patches for each source files.





diff --git a/contrib/elf2dmp/download.c b/contrib/elf2dmp/download.c
index 902dc04ffa5c..ec8d33ba1e4b 100644
--- a/contrib/elf2dmp/download.c
+++ b/contrib/elf2dmp/download.c
@@ -9,14 +9,14 @@
  #include 
  #include "download.h"

-int download_url(const char *name, const char *url)
+bool download_url(const char *name, const char *url)
  {
-int err = 1;
+bool success = false;
  FILE *file;
  CURL *curl = curl_easy_init();

  if (!curl) {
-return 1;
+return success;


Why not just "return false" ? "return success" makes it look
like a success-path, not a failure-path.


It is a mistake. I'll fix in the next version.




  }

  file = fopen(name, "wb");
@@ -33,11 +33,11 @@ int download_url(const char *name, const char *url)
  unlink(name);
  fclose(file);
  } else {
-err = fclose(file);
+success = !fclose(file);
  }

  out_curl:
  curl_easy_cleanup(curl);

-return err;
+return success;
  }



@@ -186,13 +186,13 @@ static void 
win_context_init_from_qemu_cpu_state(WinContext64 *ctx,
   * Finds paging-structure hierarchy base,
   * if previously set doesn't give access to kernel structures
   */
-static int fix_dtb(struct va_space *vs, QEMU_Elf *qe)
+static bool fix_dtb(struct va_space *vs, QEMU_Elf *qe)
  {
  /*
   * Firstly, test previously set DTB.
   */
  if (va_space_resolve(vs, SharedUserData)) {
-return 0;
+return true;
  }

  /*
@@ -206,7 +206,7 @@ static int fix_dtb(struct va_space *vs, QEMU_Elf *qe)
  va_space_set_dtb(vs, s->cr[3]);
  printf("DTB 0x%016"PRIx64" has been found from CPU #%zu"
  " as system task CR3\n", vs->dtb, i);
-return !(va_space_resolve(vs, SharedUserData));
+return !!(va_space_resolve(vs, SharedUserData));


If the function returns bool type, we don't need the !! idiom
to coerce the value to bool.


va_space_resolve() returns void *.

Regards,
Akihiko Odaki



Re: [PATCH v4] target/riscv: mcountinhibit, mcounteren, scounteren, hcounteren is 32-bit

2024-03-05 Thread Alistair Francis
On Fri, Feb 2, 2024 at 9:42 PM Vadim Shakirov
 wrote:
>
> mcountinhibit, mcounteren, scounteren and hcounteren must always be 32-bit
> by privileged spec
>
> Signed-off-by: Vadim Shakirov 

Thanks!

Applied to riscv-to-apply.next

Alistair

> ---
>  target/riscv/cpu.h |  8 
>  target/riscv/machine.c | 16 
>  2 files changed, 12 insertions(+), 12 deletions(-)
>
> diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
> index 5138187727..cf1867a6e2 100644
> --- a/target/riscv/cpu.h
> +++ b/target/riscv/cpu.h
> @@ -271,7 +271,7 @@ struct CPUArchState {
>  target_ulong hstatus;
>  target_ulong hedeleg;
>  uint64_t hideleg;
> -target_ulong hcounteren;
> +uint32_t hcounteren;
>  target_ulong htval;
>  target_ulong htinst;
>  target_ulong hgatp;
> @@ -334,10 +334,10 @@ struct CPUArchState {
>   */
>  bool two_stage_indirect_lookup;
>
> -target_ulong scounteren;
> -target_ulong mcounteren;
> +uint32_t scounteren;
> +uint32_t mcounteren;
>
> -target_ulong mcountinhibit;
> +uint32_t mcountinhibit;
>
>  /* PMU counter state */
>  PMUCTRState pmu_ctrs[RV_MAX_MHPMCOUNTERS];
> diff --git a/target/riscv/machine.c b/target/riscv/machine.c
> index 72fe2374dc..a4d47ec17e 100644
> --- a/target/riscv/machine.c
> +++ b/target/riscv/machine.c
> @@ -79,14 +79,14 @@ static bool hyper_needed(void *opaque)
>
>  static const VMStateDescription vmstate_hyper = {
>  .name = "cpu/hyper",
> -.version_id = 3,
> -.minimum_version_id = 3,
> +.version_id = 4,
> +.minimum_version_id = 4,
>  .needed = hyper_needed,
>  .fields = (const VMStateField[]) {
>  VMSTATE_UINTTL(env.hstatus, RISCVCPU),
>  VMSTATE_UINTTL(env.hedeleg, RISCVCPU),
>  VMSTATE_UINT64(env.hideleg, RISCVCPU),
> -VMSTATE_UINTTL(env.hcounteren, RISCVCPU),
> +VMSTATE_UINT32(env.hcounteren, RISCVCPU),
>  VMSTATE_UINTTL(env.htval, RISCVCPU),
>  VMSTATE_UINTTL(env.htinst, RISCVCPU),
>  VMSTATE_UINTTL(env.hgatp, RISCVCPU),
> @@ -354,8 +354,8 @@ static const VMStateDescription vmstate_jvt = {
>
>  const VMStateDescription vmstate_riscv_cpu = {
>  .name = "cpu",
> -.version_id = 9,
> -.minimum_version_id = 9,
> +.version_id = 10,
> +.minimum_version_id = 10,
>  .post_load = riscv_cpu_post_load,
>  .fields = (const VMStateField[]) {
>  VMSTATE_UINTTL_ARRAY(env.gpr, RISCVCPU, 32),
> @@ -398,9 +398,9 @@ const VMStateDescription vmstate_riscv_cpu = {
>  VMSTATE_UINTTL(env.mtval, RISCVCPU),
>  VMSTATE_UINTTL(env.miselect, RISCVCPU),
>  VMSTATE_UINTTL(env.siselect, RISCVCPU),
> -VMSTATE_UINTTL(env.scounteren, RISCVCPU),
> -VMSTATE_UINTTL(env.mcounteren, RISCVCPU),
> -VMSTATE_UINTTL(env.mcountinhibit, RISCVCPU),
> +VMSTATE_UINT32(env.scounteren, RISCVCPU),
> +VMSTATE_UINT32(env.mcounteren, RISCVCPU),
> +VMSTATE_UINT32(env.mcountinhibit, RISCVCPU),
>  VMSTATE_STRUCT_ARRAY(env.pmu_ctrs, RISCVCPU, RV_MAX_MHPMCOUNTERS, 0,
>   vmstate_pmu_ctr_state, PMUCTRState),
>  VMSTATE_UINTTL_ARRAY(env.mhpmevent_val, RISCVCPU, RV_MAX_MHPMEVENTS),
> --
> 2.34.1
>
>



Re: [PATCH v4] target/riscv: mcountinhibit, mcounteren, scounteren, hcounteren is 32-bit

2024-03-05 Thread Alistair Francis
On Fri, Feb 2, 2024 at 9:42 PM Vadim Shakirov
 wrote:
>
> mcountinhibit, mcounteren, scounteren and hcounteren must always be 32-bit
> by privileged spec
>
> Signed-off-by: Vadim Shakirov 

Reviewed-by: Alistair Francis 

Alistair

> ---
>  target/riscv/cpu.h |  8 
>  target/riscv/machine.c | 16 
>  2 files changed, 12 insertions(+), 12 deletions(-)
>
> diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
> index 5138187727..cf1867a6e2 100644
> --- a/target/riscv/cpu.h
> +++ b/target/riscv/cpu.h
> @@ -271,7 +271,7 @@ struct CPUArchState {
>  target_ulong hstatus;
>  target_ulong hedeleg;
>  uint64_t hideleg;
> -target_ulong hcounteren;
> +uint32_t hcounteren;
>  target_ulong htval;
>  target_ulong htinst;
>  target_ulong hgatp;
> @@ -334,10 +334,10 @@ struct CPUArchState {
>   */
>  bool two_stage_indirect_lookup;
>
> -target_ulong scounteren;
> -target_ulong mcounteren;
> +uint32_t scounteren;
> +uint32_t mcounteren;
>
> -target_ulong mcountinhibit;
> +uint32_t mcountinhibit;
>
>  /* PMU counter state */
>  PMUCTRState pmu_ctrs[RV_MAX_MHPMCOUNTERS];
> diff --git a/target/riscv/machine.c b/target/riscv/machine.c
> index 72fe2374dc..a4d47ec17e 100644
> --- a/target/riscv/machine.c
> +++ b/target/riscv/machine.c
> @@ -79,14 +79,14 @@ static bool hyper_needed(void *opaque)
>
>  static const VMStateDescription vmstate_hyper = {
>  .name = "cpu/hyper",
> -.version_id = 3,
> -.minimum_version_id = 3,
> +.version_id = 4,
> +.minimum_version_id = 4,
>  .needed = hyper_needed,
>  .fields = (const VMStateField[]) {
>  VMSTATE_UINTTL(env.hstatus, RISCVCPU),
>  VMSTATE_UINTTL(env.hedeleg, RISCVCPU),
>  VMSTATE_UINT64(env.hideleg, RISCVCPU),
> -VMSTATE_UINTTL(env.hcounteren, RISCVCPU),
> +VMSTATE_UINT32(env.hcounteren, RISCVCPU),
>  VMSTATE_UINTTL(env.htval, RISCVCPU),
>  VMSTATE_UINTTL(env.htinst, RISCVCPU),
>  VMSTATE_UINTTL(env.hgatp, RISCVCPU),
> @@ -354,8 +354,8 @@ static const VMStateDescription vmstate_jvt = {
>
>  const VMStateDescription vmstate_riscv_cpu = {
>  .name = "cpu",
> -.version_id = 9,
> -.minimum_version_id = 9,
> +.version_id = 10,
> +.minimum_version_id = 10,
>  .post_load = riscv_cpu_post_load,
>  .fields = (const VMStateField[]) {
>  VMSTATE_UINTTL_ARRAY(env.gpr, RISCVCPU, 32),
> @@ -398,9 +398,9 @@ const VMStateDescription vmstate_riscv_cpu = {
>  VMSTATE_UINTTL(env.mtval, RISCVCPU),
>  VMSTATE_UINTTL(env.miselect, RISCVCPU),
>  VMSTATE_UINTTL(env.siselect, RISCVCPU),
> -VMSTATE_UINTTL(env.scounteren, RISCVCPU),
> -VMSTATE_UINTTL(env.mcounteren, RISCVCPU),
> -VMSTATE_UINTTL(env.mcountinhibit, RISCVCPU),
> +VMSTATE_UINT32(env.scounteren, RISCVCPU),
> +VMSTATE_UINT32(env.mcounteren, RISCVCPU),
> +VMSTATE_UINT32(env.mcountinhibit, RISCVCPU),
>  VMSTATE_STRUCT_ARRAY(env.pmu_ctrs, RISCVCPU, RV_MAX_MHPMCOUNTERS, 0,
>   vmstate_pmu_ctr_state, PMUCTRState),
>  VMSTATE_UINTTL_ARRAY(env.mhpmevent_val, RISCVCPU, RV_MAX_MHPMEVENTS),
> --
> 2.34.1
>
>



Re: [PATCH] hw/core/machine-smp: Remove deprecated "parameter=0" SMP configurations

2024-03-05 Thread Prasad Pandit
Hello Zhao,

On Wed, 6 Mar 2024 at 08:49, Zhao Liu  wrote:
>> then checking 'config->has_maxcpus ?' above is probably not required I
>> think. It could just be
>>
>>maxcpus = config->maxcpus
>
> Yes.
>
> > If a user does not specify config->maxcpus with -smp option, then it
> > could default to zero(0) in 'config' parameter? (same for other config
> > fields)
>
> Yes. I could post another series for this cleanup soon.
> The above change you suggested doesn't require API changes ;-).

* Great!  (Communication is the most difficult skill to master. :))

* If you plan to send a separate patch for above refactoring, then I'd
add Reviewed-by for this one.

Reviewed-by: Prasad Pandit 

Thank you.
---
  - Prasad




Re: [PATCH] target/riscv: move ratified/frozen exts to non-experimental

2024-03-05 Thread Alistair Francis
On Sat, Mar 2, 2024 at 12:41 AM Daniel Henrique Barboza
 wrote:
>
> smaia and ssaia were ratified in August 25th 2023 [1].
>
> zvfh and zvfhmin were ratified in August 2nd 2023 [2].
>
> zfbfmin and zvfbf(min|wma) are frozen and moved to public review since
> Dec 16th 2023 [3].
>
> zaamo and zalrsc are both marked as "Frozen" since January 24th 2024
> [4].
>
> [1] https://jira.riscv.org/browse/RVS-438
> [2] https://jira.riscv.org/browse/RVS-871
> [3] https://jira.riscv.org/browse/RVS-704
> [4] https://jira.riscv.org/browse/RVS-1995
>
> Signed-off-by: Daniel Henrique Barboza 

Thanks!

Applied to riscv-to-apply.next

Alistair

> ---
>  target/riscv/cpu.c | 22 +-
>  1 file changed, 9 insertions(+), 13 deletions(-)
>
> diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
> index fd0c7efdda..f5d30510ef 100644
> --- a/target/riscv/cpu.c
> +++ b/target/riscv/cpu.c
> @@ -1463,17 +1463,26 @@ const RISCVCPUMultiExtConfig riscv_cpu_extensions[] = 
> {
>  MULTI_EXT_CFG_BOOL("zihintntl", ext_zihintntl, true),
>  MULTI_EXT_CFG_BOOL("zihintpause", ext_zihintpause, true),
>  MULTI_EXT_CFG_BOOL("zacas", ext_zacas, false),
> +MULTI_EXT_CFG_BOOL("zaamo", ext_zaamo, false),
> +MULTI_EXT_CFG_BOOL("zalrsc", ext_zalrsc, false),
>  MULTI_EXT_CFG_BOOL("zawrs", ext_zawrs, true),
>  MULTI_EXT_CFG_BOOL("zfa", ext_zfa, true),
> +MULTI_EXT_CFG_BOOL("zfbfmin", ext_zfbfmin, false),
>  MULTI_EXT_CFG_BOOL("zfh", ext_zfh, false),
>  MULTI_EXT_CFG_BOOL("zfhmin", ext_zfhmin, false),
>  MULTI_EXT_CFG_BOOL("zve32f", ext_zve32f, false),
>  MULTI_EXT_CFG_BOOL("zve64f", ext_zve64f, false),
>  MULTI_EXT_CFG_BOOL("zve64d", ext_zve64d, false),
> +MULTI_EXT_CFG_BOOL("zvfbfmin", ext_zvfbfmin, false),
> +MULTI_EXT_CFG_BOOL("zvfbfwma", ext_zvfbfwma, false),
> +MULTI_EXT_CFG_BOOL("zvfh", ext_zvfh, false),
> +MULTI_EXT_CFG_BOOL("zvfhmin", ext_zvfhmin, false),
>  MULTI_EXT_CFG_BOOL("sstc", ext_sstc, true),
>
> +MULTI_EXT_CFG_BOOL("smaia", ext_smaia, false),
>  MULTI_EXT_CFG_BOOL("smepmp", ext_smepmp, false),
>  MULTI_EXT_CFG_BOOL("smstateen", ext_smstateen, false),
> +MULTI_EXT_CFG_BOOL("ssaia", ext_ssaia, false),
>  MULTI_EXT_CFG_BOOL("svade", ext_svade, false),
>  MULTI_EXT_CFG_BOOL("svadu", ext_svadu, true),
>  MULTI_EXT_CFG_BOOL("svinval", ext_svinval, false),
> @@ -1561,19 +1570,6 @@ const RISCVCPUMultiExtConfig riscv_cpu_vendor_exts[] = 
> {
>
>  /* These are experimental so mark with 'x-' */
>  const RISCVCPUMultiExtConfig riscv_cpu_experimental_exts[] = {
> -MULTI_EXT_CFG_BOOL("x-smaia", ext_smaia, false),
> -MULTI_EXT_CFG_BOOL("x-ssaia", ext_ssaia, false),
> -
> -MULTI_EXT_CFG_BOOL("x-zaamo", ext_zaamo, false),
> -MULTI_EXT_CFG_BOOL("x-zalrsc", ext_zalrsc, false),
> -
> -MULTI_EXT_CFG_BOOL("x-zvfh", ext_zvfh, false),
> -MULTI_EXT_CFG_BOOL("x-zvfhmin", ext_zvfhmin, false),
> -
> -MULTI_EXT_CFG_BOOL("x-zfbfmin", ext_zfbfmin, false),
> -MULTI_EXT_CFG_BOOL("x-zvfbfmin", ext_zvfbfmin, false),
> -MULTI_EXT_CFG_BOOL("x-zvfbfwma", ext_zvfbfwma, false),
> -
>  DEFINE_PROP_END_OF_LIST(),
>  };
>
> --
> 2.43.2
>
>



Re: [PATCH] target/riscv: move ratified/frozen exts to non-experimental

2024-03-05 Thread Alistair Francis
On Sat, Mar 2, 2024 at 12:41 AM Daniel Henrique Barboza
 wrote:
>
> smaia and ssaia were ratified in August 25th 2023 [1].
>
> zvfh and zvfhmin were ratified in August 2nd 2023 [2].
>
> zfbfmin and zvfbf(min|wma) are frozen and moved to public review since
> Dec 16th 2023 [3].
>
> zaamo and zalrsc are both marked as "Frozen" since January 24th 2024
> [4].
>
> [1] https://jira.riscv.org/browse/RVS-438
> [2] https://jira.riscv.org/browse/RVS-871
> [3] https://jira.riscv.org/browse/RVS-704
> [4] https://jira.riscv.org/browse/RVS-1995
>
> Signed-off-by: Daniel Henrique Barboza 

Reviewed-by: Alistair Francis 

Alistair

> ---
>  target/riscv/cpu.c | 22 +-
>  1 file changed, 9 insertions(+), 13 deletions(-)
>
> diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
> index fd0c7efdda..f5d30510ef 100644
> --- a/target/riscv/cpu.c
> +++ b/target/riscv/cpu.c
> @@ -1463,17 +1463,26 @@ const RISCVCPUMultiExtConfig riscv_cpu_extensions[] = 
> {
>  MULTI_EXT_CFG_BOOL("zihintntl", ext_zihintntl, true),
>  MULTI_EXT_CFG_BOOL("zihintpause", ext_zihintpause, true),
>  MULTI_EXT_CFG_BOOL("zacas", ext_zacas, false),
> +MULTI_EXT_CFG_BOOL("zaamo", ext_zaamo, false),
> +MULTI_EXT_CFG_BOOL("zalrsc", ext_zalrsc, false),
>  MULTI_EXT_CFG_BOOL("zawrs", ext_zawrs, true),
>  MULTI_EXT_CFG_BOOL("zfa", ext_zfa, true),
> +MULTI_EXT_CFG_BOOL("zfbfmin", ext_zfbfmin, false),
>  MULTI_EXT_CFG_BOOL("zfh", ext_zfh, false),
>  MULTI_EXT_CFG_BOOL("zfhmin", ext_zfhmin, false),
>  MULTI_EXT_CFG_BOOL("zve32f", ext_zve32f, false),
>  MULTI_EXT_CFG_BOOL("zve64f", ext_zve64f, false),
>  MULTI_EXT_CFG_BOOL("zve64d", ext_zve64d, false),
> +MULTI_EXT_CFG_BOOL("zvfbfmin", ext_zvfbfmin, false),
> +MULTI_EXT_CFG_BOOL("zvfbfwma", ext_zvfbfwma, false),
> +MULTI_EXT_CFG_BOOL("zvfh", ext_zvfh, false),
> +MULTI_EXT_CFG_BOOL("zvfhmin", ext_zvfhmin, false),
>  MULTI_EXT_CFG_BOOL("sstc", ext_sstc, true),
>
> +MULTI_EXT_CFG_BOOL("smaia", ext_smaia, false),
>  MULTI_EXT_CFG_BOOL("smepmp", ext_smepmp, false),
>  MULTI_EXT_CFG_BOOL("smstateen", ext_smstateen, false),
> +MULTI_EXT_CFG_BOOL("ssaia", ext_ssaia, false),
>  MULTI_EXT_CFG_BOOL("svade", ext_svade, false),
>  MULTI_EXT_CFG_BOOL("svadu", ext_svadu, true),
>  MULTI_EXT_CFG_BOOL("svinval", ext_svinval, false),
> @@ -1561,19 +1570,6 @@ const RISCVCPUMultiExtConfig riscv_cpu_vendor_exts[] = 
> {
>
>  /* These are experimental so mark with 'x-' */
>  const RISCVCPUMultiExtConfig riscv_cpu_experimental_exts[] = {
> -MULTI_EXT_CFG_BOOL("x-smaia", ext_smaia, false),
> -MULTI_EXT_CFG_BOOL("x-ssaia", ext_ssaia, false),
> -
> -MULTI_EXT_CFG_BOOL("x-zaamo", ext_zaamo, false),
> -MULTI_EXT_CFG_BOOL("x-zalrsc", ext_zalrsc, false),
> -
> -MULTI_EXT_CFG_BOOL("x-zvfh", ext_zvfh, false),
> -MULTI_EXT_CFG_BOOL("x-zvfhmin", ext_zvfhmin, false),
> -
> -MULTI_EXT_CFG_BOOL("x-zfbfmin", ext_zfbfmin, false),
> -MULTI_EXT_CFG_BOOL("x-zvfbfmin", ext_zvfbfmin, false),
> -MULTI_EXT_CFG_BOOL("x-zvfbfwma", ext_zvfbfwma, false),
> -
>  DEFINE_PROP_END_OF_LIST(),
>  };
>
> --
> 2.43.2
>
>



Re: What riscv tracing tools do you recommend and how are they accurate for measurements?

2024-03-05 Thread Alistair Francis
On Thu, Feb 29, 2024 at 11:21 PM Nazerke Turtayeva  wrote:
>
> Hi everyone,
>
> Recently, I was planning to measure the performance of my application of 
> interest for potential RISC-V hardware. Hence, I started my simulations from 
> Spike to analyze dynamic instruction traces and instruction count, 
> nevertheless given it does not support multithreading, I started using Qemu 
> to test my app too. However, it seems like I cannot rely on timing results of 
> Qemu for comparing different implementations. Accordingly, given I am brand 
> new to the Qemu ecosystem, I was wondering whether I am missing some 
> important mainstream instrumentation and tracing tools that I can use for 
> performance evaluation of my target app in other ways. Particularly, I want 
> to understand implications of adding custom ISA instructions to the 
> performance of my application.

Hello,

QEMU is an emulator so it isn't great at timing analysis.

QEMU is useful for instruction traces though. If you use icount [1]
you can get a deterministic-ish setup which is very useful for
instruction counting during execution. I'm not sure what custom
instructions you are adding, but you can test if they reduce the
number of instructions executed. Note that QEMU doesn't model timing
though, so it might not be an accurate representation of real life
performance.

You can use a plugin (see [2] for some examples) to generate
instruction, memory or other more specific traces.

1: https://www.qemu.org/docs/master/devel/tcg-icount.html
2: https://www.qemu.org/docs/master/devel/tcg-plugins.html#example-plugins

Alistair

>
> In this regard, do you have any recommendations on where I can look?
>
> Thanks,
> Best wishes
>
> --
> Nazerke Turtayeva
> Graduate Student
> Electrical and Computer Engineering, Computer Science
> Email: nturtay...@ucsb.edu
> UC Santa Barbara



Re: [Stable-8.2.1 61/71] linux-user/riscv: Adjust vdso signal frame cfa offsets

2024-03-05 Thread Alistair Francis
On Sun, Mar 3, 2024 at 8:34 PM Andreas Schwab  wrote:
>
> On Jan 28 2024, Michael Tokarev wrote:
>
> > From: Richard Henderson 
> >
> > A typo in sizeof_reg put the registers at the wrong offset.
> >
> > Simplify the expressions to use positive addresses from the
> > start of uc_mcontext instead of negative addresses from the
> > end of uc_mcontext.
>
> This breaks the testsuite of libunwind.  The test Gtest-resume-sig and
> all dependent tests hang.  Reverting this commit fixes them.

Do you have any more details? It seems strange that this commit is
breaking something as it looks to be correct

Alistair

>
> --
> Andreas Schwab, sch...@linux-m68k.org
> GPG Key fingerprint = 7578 EB47 D4E5 4D69 2510  2552 DF73 E780 A9DA AEC1
> "And now for something completely different."
>



Re: [RFC PATCH v7 00/23] target/arm: Implement FEAT_NMI and FEAT_GICv3_NMI

2024-03-05 Thread Richard Henderson

On 3/5/24 17:56, Jinjie Ruan via wrote:

This patch set implements FEAT_NMI and FEAT_GICv3_NMI for armv8. These
introduce support for a new category of interrupts in the architecture
which we can use to provide NMI like functionality.

There are two modes for using this FEAT_NMI. When PSTATE.ALLINT or
PSTATE.SP & SCTLR_ELx.SCTLR_SPINTMASK is set, any entry to ELx causes all
interrupts including those with superpriority to be masked on entry to ELn
until the mask is explicitly removed by software or hardware. PSTATE.ALLINT
can be managed by software using the new register control ALLINT.ALLINT.
Independent controls are provided for this feature at each EL, usage at EL1
should not disrupt EL2 or EL3.

I have tested it with the following linux patches which try to support
FEAT_NMI in linux kernel:


https://lore.kernel.org/linux-arm-kernel/Y4sH5qX5bK9xfEBp@lpieralisi/T/#mb4ba4a2c045bf72c10c2202c1dd1b82d3240dc88

In the test, SGI, PPI and SPI interrupts can all be set to have super priority
to be converted to a hardware NMI interrupt. The SGI is tested with kernel
IPI as NMI framework, softlockup, hardlockup and kgdb test cases, and the PPI
interrupt is tested with "perf top" command with hardware NMI enabled, and
the SPI interrupt is tested with a custom test module, in which NMI interrupts
can be received and sent normally.


As far as I can see, this patch set is good to go.  I'm fairly confident of the CPU side 
of the equation, but the GIC could use a second set of eyes.



r~



Re: [RFC PATCH v7 19/23] hw/intc/arm_gicv3: Implement NMI interrupt prioirty

2024-03-05 Thread Richard Henderson

On 3/5/24 17:57, Jinjie Ruan via wrote:

If GICD_CTLR_DS bit is zero and the NMI is non-secure, the NMI prioirty
is higher than 0x80, otherwise it is higher than 0x0. And save NMI
super prioirty information in hppi.superprio to deliver NMI exception.
Since both GICR and GICD can deliver NMI, it is both necessary to check
whether the pending irq is NMI in gicv3_redist_update_noirqset and
gicv3_update_noirqset. And In irqbetter(), only a non-NMI with the same
priority and a smaller interrupt number can be preempted but not NMI.

Signed-off-by: Jinjie Ruan
---
v7:
- Reorder the irqbetter() code for clarity.
- Eliminate the has_superprio local variable for gicv3_get_priority().
- false -> cs->hpplpi.superprio in gicv3_redist_update_noirqset().
- 0x0 -> false in arm_gicv3_common_reset_hold().
- Clear superprio in several places for hppi, hpplpi and hppvlpi.
v6:
- Put the "extract superprio info" logic into gicv3_get_priority().
- Update the comment in irqbetter().
- Reset the cs->hppi.superprio to 0x0.
- Set hppi.superprio to false for LPI.
v4:
- Replace is_nmi with has_superprio to not a mix NMI and superpriority.
- Update the comment in irqbetter().
- Extract gicv3_get_priority() to avoid code repeat.
---


Reviewed-by: Richard Henderson 

r~



Re: [PATCH V2 1/1] target/loongarch: Fixed tlb huge page loading issue

2024-03-05 Thread Richard Henderson

On 3/5/24 17:52, lixianglai wrote:
The LDDIR_PS variable is not described in detail in the manual, but is only an 
intermediate variable to assist in page size calculation during tcg simulation.


This is exactly why I believe adding this intermediate variable is wrong.

What happens if LDPTE is *not* preceded by LDDIR?  It's not the usual way a tlb fill 
routine works, but *something* should happen if you construct a valid huge page tlb entry 
by hand and pass it directly to LDPTE.


With your implementation, this will not work because lddir_ps will not be initialized. 
But I expect that on real hardware it would work.


If this does not work on real hardware, then there *is* some heretofore undocumented 
hardware state.  If so, then we need a description of this state from the hardware 
engineers -- the documentation of LDDIR and LDPTE need updating.  Finally, this new 
hardware state needs to be added to the migration state.



r~



[RFC PATCH v7 04/23] target/arm: Implement ALLINT MSR (immediate)

2024-03-05 Thread Jinjie Ruan via
Add ALLINT MSR (immediate) to decodetree, in which the CRm is 0b000x. The
EL0 check is necessary to ALLINT, and the EL1 check is necessary when
imm == 1. So implement it inline for EL2/3, or EL1 with imm==0. Avoid the
unconditional write to pc and use raise_exception_ra to unwind.

Signed-off-by: Jinjie Ruan 
Reviewed-by: Richard Henderson 
---
v7:
- Add Reviewed-by.
v6:
- Fix DISAS_TOO_MANY to DISAS_UPDATE_EXIT and add the comment.
v5:
- Drop the & 1 in trans_MSR_i_ALLINT().
- Simplify and merge msr_i_allint() and allint_check().
- Rename msr_i_allint() to msr_set_allint_el1().
v4:
- Fix the ALLINT MSR (immediate) decodetree implementation.
- Remove arm_is_el2_enabled() check in allint_check().
- Update env->allint to env->pstate.
- Only call allint_check() when imm == 1.
- Simplify the allint_check() to not pass "op" and extract.
- Implement it inline for EL2/3, or EL1 with imm==0.
- Pass (a->imm & 1) * PSTATE_ALLINT (i64) to simplfy the ALLINT set/clear.
v3:
- Remove EL0 check in allint_check().
- Add TALLINT check for EL1 in allint_check().
- Remove unnecessarily arm_rebuild_hflags() in msr_i_allint helper.
---
 target/arm/tcg/a64.decode  |  1 +
 target/arm/tcg/helper-a64.c| 12 
 target/arm/tcg/helper-a64.h|  1 +
 target/arm/tcg/translate-a64.c | 19 +++
 4 files changed, 33 insertions(+)

diff --git a/target/arm/tcg/a64.decode b/target/arm/tcg/a64.decode
index 8a20dce3c8..0e7656fd15 100644
--- a/target/arm/tcg/a64.decode
+++ b/target/arm/tcg/a64.decode
@@ -207,6 +207,7 @@ MSR_i_DIT   1101 0101  0 011 0100  010 1 
@msr_i
 MSR_i_TCO   1101 0101  0 011 0100  100 1 @msr_i
 MSR_i_DAIFSET   1101 0101  0 011 0100  110 1 @msr_i
 MSR_i_DAIFCLEAR 1101 0101  0 011 0100  111 1 @msr_i
+MSR_i_ALLINT1101 0101  0 001 0100 000 imm:1 000 1
 MSR_i_SVCR  1101 0101  0 011 0100 0 mask:2 imm:1 011 1
 
 # MRS, MSR (register), SYS, SYSL. These are all essentially the
diff --git a/target/arm/tcg/helper-a64.c b/target/arm/tcg/helper-a64.c
index ebaa7f00df..7818537890 100644
--- a/target/arm/tcg/helper-a64.c
+++ b/target/arm/tcg/helper-a64.c
@@ -66,6 +66,18 @@ void HELPER(msr_i_spsel)(CPUARMState *env, uint32_t imm)
 update_spsel(env, imm);
 }
 
+void HELPER(msr_set_allint_el1)(CPUARMState *env)
+{
+/* ALLINT update to PSTATE. */
+if (arm_hcrx_el2_eff(env) & HCRX_TALLINT) {
+raise_exception_ra(env, EXCP_UDEF,
+   syn_aa64_sysregtrap(0, 1, 0, 4, 1, 0x1f, 0),
+   exception_target_el(env), GETPC());
+}
+
+env->pstate |= PSTATE_ALLINT;
+}
+
 static void daif_check(CPUARMState *env, uint32_t op,
uint32_t imm, uintptr_t ra)
 {
diff --git a/target/arm/tcg/helper-a64.h b/target/arm/tcg/helper-a64.h
index 575a5dab7d..0518165399 100644
--- a/target/arm/tcg/helper-a64.h
+++ b/target/arm/tcg/helper-a64.h
@@ -22,6 +22,7 @@ DEF_HELPER_FLAGS_1(rbit64, TCG_CALL_NO_RWG_SE, i64, i64)
 DEF_HELPER_2(msr_i_spsel, void, env, i32)
 DEF_HELPER_2(msr_i_daifset, void, env, i32)
 DEF_HELPER_2(msr_i_daifclear, void, env, i32)
+DEF_HELPER_1(msr_set_allint_el1, void, env)
 DEF_HELPER_3(vfp_cmph_a64, i64, f16, f16, ptr)
 DEF_HELPER_3(vfp_cmpeh_a64, i64, f16, f16, ptr)
 DEF_HELPER_3(vfp_cmps_a64, i64, f32, f32, ptr)
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
index 340265beb0..21758b290d 100644
--- a/target/arm/tcg/translate-a64.c
+++ b/target/arm/tcg/translate-a64.c
@@ -2036,6 +2036,25 @@ static bool trans_MSR_i_DAIFCLEAR(DisasContext *s, arg_i 
*a)
 return true;
 }
 
+static bool trans_MSR_i_ALLINT(DisasContext *s, arg_i *a)
+{
+if (!dc_isar_feature(aa64_nmi, s) || s->current_el == 0) {
+return false;
+}
+
+if (a->imm == 0) {
+clear_pstate_bits(PSTATE_ALLINT);
+} else if (s->current_el > 1) {
+set_pstate_bits(PSTATE_ALLINT);
+} else {
+gen_helper_msr_set_allint_el1(tcg_env);
+}
+
+/* Exit the cpu loop to re-evaluate pending IRQs. */
+s->base.is_jmp = DISAS_UPDATE_EXIT;
+return true;
+}
+
 static bool trans_MSR_i_SVCR(DisasContext *s, arg_MSR_i_SVCR *a)
 {
 if (!dc_isar_feature(aa64_sme, s) || a->mask == 0) {
-- 
2.34.1




[RFC PATCH v7 08/23] target/arm: Handle IS/FS in ISR_EL1 for NMI

2024-03-05 Thread Jinjie Ruan via
Add IS and FS bit in ISR_EL1 and handle the read. With CPU_INTERRUPT_NMI or
CPU_INTERRUPT_VNMI, both CPSR_I and ISR_IS must be set. With
CPU_INTERRUPT_VFIQ and HCRX_EL2.VFNMI set, both CPSR_F and ISR_FS must be set.

Signed-off-by: Jinjie Ruan 
Reviewed-by: Richard Henderson 
---
v7:
- env->cp15.hcrx_el2 -> arm_hcrx_el2_eff().
- Add Reviewed-by.
v6:
- Verify that HCR_EL2.VF is set before checking VFNMI.
v4;
- Also handle VNMI.
v3:
- CPU_INTERRUPT_NMI do not set FIQ, so remove it.
- With CPU_INTERRUPT_NMI, both CPSR_I and ISR_IS must be set.
---
 target/arm/cpu.h|  2 ++
 target/arm/helper.c | 14 ++
 2 files changed, 16 insertions(+)

diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index de9446c68c..97f276559f 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -1467,6 +1467,8 @@ FIELD(CPTR_EL3, TCPAC, 31, 1)
 #define CPSR_N (1U << 31)
 #define CPSR_NZCV (CPSR_N | CPSR_Z | CPSR_C | CPSR_V)
 #define CPSR_AIF (CPSR_A | CPSR_I | CPSR_F)
+#define ISR_FS (1U << 9)
+#define ISR_IS (1U << 10)
 
 #define CPSR_IT (CPSR_IT_0_1 | CPSR_IT_2_7)
 #define CACHED_CPSR_BITS (CPSR_T | CPSR_AIF | CPSR_GE | CPSR_IT | CPSR_Q \
diff --git a/target/arm/helper.c b/target/arm/helper.c
index 7cdc90e9e3..15f72fa425 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -2018,15 +2018,29 @@ static uint64_t isr_read(CPUARMState *env, const 
ARMCPRegInfo *ri)
 if (cs->interrupt_request & CPU_INTERRUPT_VIRQ) {
 ret |= CPSR_I;
 }
+if (cs->interrupt_request & CPU_INTERRUPT_VNMI) {
+ret |= ISR_IS;
+ret |= CPSR_I;
+}
 } else {
 if (cs->interrupt_request & CPU_INTERRUPT_HARD) {
 ret |= CPSR_I;
 }
+
+if (cs->interrupt_request & CPU_INTERRUPT_NMI) {
+ret |= ISR_IS;
+ret |= CPSR_I;
+}
 }
 
 if (hcr_el2 & HCR_FMO) {
 if (cs->interrupt_request & CPU_INTERRUPT_VFIQ) {
 ret |= CPSR_F;
+
+if ((arm_hcr_el2_eff(env) & HCR_VF) &&
+(arm_hcrx_el2_eff(env) & HCRX_VFNMI)) {
+ret |= ISR_FS;
+}
 }
 } else {
 if (cs->interrupt_request & CPU_INTERRUPT_FIQ) {
-- 
2.34.1




[RFC PATCH v7 05/23] target/arm: Support MSR access to ALLINT

2024-03-05 Thread Jinjie Ruan via
Support ALLINT msr access as follow:
mrs , ALLINT// read allint
msr ALLINT, // write allint with imm

Signed-off-by: Jinjie Ruan 
Reviewed-by: Richard Henderson 
---
v5:
- Add Reviewed-by.
v4:
- Remove arm_is_el2_enabled() check in allint_check().
- Change to env->pstate instead of env->allint.
v3:
- Remove EL0 check in aa64_allint_access() which alreay checks in .access
  PL1_RW.
- Use arm_hcrx_el2_eff() in aa64_allint_access() instead of env->cp15.hcrx_el2.
- Make ALLINT msr access function controlled by aa64_nmi.
---
 target/arm/helper.c | 34 ++
 1 file changed, 34 insertions(+)

diff --git a/target/arm/helper.c b/target/arm/helper.c
index affa493141..497b6e4bdf 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -4618,6 +4618,36 @@ static void aa64_daif_write(CPUARMState *env, const 
ARMCPRegInfo *ri,
 env->daif = value & PSTATE_DAIF;
 }
 
+static void aa64_allint_write(CPUARMState *env, const ARMCPRegInfo *ri,
+  uint64_t value)
+{
+env->pstate = (env->pstate & ~PSTATE_ALLINT) | (value & PSTATE_ALLINT);
+}
+
+static uint64_t aa64_allint_read(CPUARMState *env, const ARMCPRegInfo *ri)
+{
+return env->pstate & PSTATE_ALLINT;
+}
+
+static CPAccessResult aa64_allint_access(CPUARMState *env,
+ const ARMCPRegInfo *ri, bool isread)
+{
+if (arm_current_el(env) == 1 && (arm_hcrx_el2_eff(env) & HCRX_TALLINT)) {
+return CP_ACCESS_TRAP_EL2;
+}
+return CP_ACCESS_OK;
+}
+
+static const ARMCPRegInfo nmi_reginfo[] = {
+{ .name = "ALLINT", .state = ARM_CP_STATE_AA64,
+  .opc0 = 3, .opc1 = 0, .opc2 = 0, .crn = 4, .crm = 3,
+  .type = ARM_CP_NO_RAW,
+  .access = PL1_RW, .accessfn = aa64_allint_access,
+  .fieldoffset = offsetof(CPUARMState, pstate),
+  .writefn = aa64_allint_write, .readfn = aa64_allint_read,
+  .resetfn = arm_cp_reset_ignore },
+};
+
 static uint64_t aa64_pan_read(CPUARMState *env, const ARMCPRegInfo *ri)
 {
 return env->pstate & PSTATE_PAN;
@@ -9724,6 +9754,10 @@ void register_cp_regs_for_features(ARMCPU *cpu)
 if (cpu_isar_feature(aa64_nv2, cpu)) {
 define_arm_cp_regs(cpu, nv2_reginfo);
 }
+
+if (cpu_isar_feature(aa64_nmi, cpu)) {
+define_arm_cp_regs(cpu, nmi_reginfo);
+}
 #endif
 
 if (cpu_isar_feature(any_predinv, cpu)) {
-- 
2.34.1




[RFC PATCH v7 07/23] target/arm: Add support for NMI in arm_phys_excp_target_el()

2024-03-05 Thread Jinjie Ruan via
According to Arm GIC section 4.6.3 Interrupt superpriority, the interrupt
with superpriority is always IRQ, never FIQ, so handle NMI same as IRQ in
arm_phys_excp_target_el().

Signed-off-by: Jinjie Ruan 
Reviewed-by: Richard Henderson 
---
v4:
- Add Reviewed-by.
v3:
- Remove nmi_is_irq flag in CPUARMState.
- Handle NMI same as IRQ in arm_phys_excp_target_el().
---
 target/arm/helper.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/target/arm/helper.c b/target/arm/helper.c
index 4b4c8e279d..7cdc90e9e3 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -10570,6 +10570,7 @@ uint32_t arm_phys_excp_target_el(CPUState *cs, uint32_t 
excp_idx,
 hcr_el2 = arm_hcr_el2_eff(env);
 switch (excp_idx) {
 case EXCP_IRQ:
+case EXCP_NMI:
 scr = ((env->cp15.scr_el3 & SCR_IRQ) == SCR_IRQ);
 hcr = hcr_el2 & HCR_IMO;
 break;
-- 
2.34.1




[RFC PATCH v7 12/23] target/arm: Handle NMI in arm_cpu_do_interrupt_aarch64()

2024-03-05 Thread Jinjie Ruan via
According to Arm GIC section 4.6.3 Interrupt superpriority, the interrupt
with superpriority is always IRQ, never FIQ, so the NMI exception trap entry
behave like IRQ. And VNMI(vIRQ with Superpriority) can be raised from the
GIC or come from the hcrx_el2.HCRX_VINMI bit.

Signed-off-by: Jinjie Ruan 
Reviewed-by: Richard Henderson 
---
v7:
- Add Reviewed-by.
v6:
- Not combine VFNMI with CPU_INTERRUPT_VNMI.
v4:
- Also handle VNMI in arm_cpu_do_interrupt_aarch64().
v3:
- Remove the FIQ NMI handle.
---
 target/arm/helper.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/target/arm/helper.c b/target/arm/helper.c
index 39e76c76ee..fb52a2b721 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -11460,6 +11460,8 @@ static void arm_cpu_do_interrupt_aarch64(CPUState *cs)
 break;
 case EXCP_IRQ:
 case EXCP_VIRQ:
+case EXCP_NMI:
+case EXCP_VNMI:
 addr += 0x80;
 break;
 case EXCP_FIQ:
-- 
2.34.1




[RFC PATCH v7 16/23] hw/intc: Enable FEAT_GICv3_NMI Feature

2024-03-05 Thread Jinjie Ruan via
Added properties to enable FEAT_GICv3_NMI feature, setup distributor
and redistributor registers to indicate NMI support.

Signed-off-by: Jinjie Ruan 
Reviewed-by: Richard Henderson 
---
v4:
- Add Reviewed-by.
---
 hw/intc/arm_gicv3_common.c | 1 +
 hw/intc/arm_gicv3_dist.c   | 2 ++
 hw/intc/gicv3_internal.h   | 1 +
 include/hw/intc/arm_gicv3_common.h | 1 +
 4 files changed, 5 insertions(+)

diff --git a/hw/intc/arm_gicv3_common.c b/hw/intc/arm_gicv3_common.c
index c52f060026..2d2cea6858 100644
--- a/hw/intc/arm_gicv3_common.c
+++ b/hw/intc/arm_gicv3_common.c
@@ -569,6 +569,7 @@ static Property arm_gicv3_common_properties[] = {
 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-nmi", GICv3State, nmi_support, 0),
 DEFINE_PROP_BOOL("has-security-extensions", GICv3State, security_extn, 0),
 /*
  * Compatibility property: force 8 bits of physical priority, even
diff --git a/hw/intc/arm_gicv3_dist.c b/hw/intc/arm_gicv3_dist.c
index 9739404e35..c4e28d209a 100644
--- a/hw/intc/arm_gicv3_dist.c
+++ b/hw/intc/arm_gicv3_dist.c
@@ -412,6 +412,7 @@ static bool gicd_readl(GICv3State *s, hwaddr offset,
  *  by GICD_TYPER.IDbits)
  * MBIS == 0 (message-based SPIs not supported)
  * SecurityExtn == 1 if security extns supported
+ * NMI = 1 if Non-maskable interrupt property is supported
  * CPUNumber == 0 since for us ARE is always 1
  * ITLinesNumber == (((max SPI IntID + 1) / 32) - 1)
  */
@@ -425,6 +426,7 @@ static bool gicd_readl(GICv3State *s, hwaddr offset,
 bool dvis = s->revision >= 4;
 
 *data = (1 << 25) | (1 << 24) | (dvis << 18) | (sec_extn << 10) |
+(s->nmi_support << GICD_TYPER_NMI_SHIFT) |
 (s->lpi_enable << GICD_TYPER_LPIS_SHIFT) |
 (0xf << 19) | itlinesnumber;
 return true;
diff --git a/hw/intc/gicv3_internal.h b/hw/intc/gicv3_internal.h
index a1fc34597e..8d793243f4 100644
--- a/hw/intc/gicv3_internal.h
+++ b/hw/intc/gicv3_internal.h
@@ -70,6 +70,7 @@
 #define GICD_CTLR_E1NWF (1U << 7)
 #define GICD_CTLR_RWP   (1U << 31)
 
+#define GICD_TYPER_NMI_SHIFT   9
 #define GICD_TYPER_LPIS_SHIFT  17
 
 /* 16 bits EventId */
diff --git a/include/hw/intc/arm_gicv3_common.h 
b/include/hw/intc/arm_gicv3_common.h
index df4380141d..16c5fa7256 100644
--- a/include/hw/intc/arm_gicv3_common.h
+++ b/include/hw/intc/arm_gicv3_common.h
@@ -251,6 +251,7 @@ struct GICv3State {
 uint32_t num_irq;
 uint32_t revision;
 bool lpi_enable;
+bool nmi_support;
 bool security_extn;
 bool force_8bit_prio;
 bool irq_reset_nonsecure;
-- 
2.34.1




[RFC PATCH v7 20/23] hw/intc/arm_gicv3: Report the NMI interrupt in gicv3_cpuif_update()

2024-03-05 Thread Jinjie Ruan via
In CPU Interface, if the IRQ has the superpriority property, report
NMI to the corresponding PE.

Signed-off-by: Jinjie Ruan 
Reviewed-by: Richard Henderson 
---
v6:
- Add Reviewed-by.
v4:
- Swap the ordering of the IFs.
v3:
- Remove handling nmi_is_irq flag.
---
 hw/intc/arm_gicv3_cpuif.c | 4 
 1 file changed, 4 insertions(+)

diff --git a/hw/intc/arm_gicv3_cpuif.c b/hw/intc/arm_gicv3_cpuif.c
index 9a7d089dea..483b1bc4a3 100644
--- a/hw/intc/arm_gicv3_cpuif.c
+++ b/hw/intc/arm_gicv3_cpuif.c
@@ -967,6 +967,7 @@ void gicv3_cpuif_update(GICv3CPUState *cs)
 /* Tell the CPU about its highest priority pending interrupt */
 int irqlevel = 0;
 int fiqlevel = 0;
+int nmilevel = 0;
 ARMCPU *cpu = ARM_CPU(cs->cpu);
 CPUARMState *env = >env;
 
@@ -1005,6 +1006,8 @@ void gicv3_cpuif_update(GICv3CPUState *cs)
 
 if (isfiq) {
 fiqlevel = 1;
+} else if (cs->hppi.superprio) {
+nmilevel = 1;
 } else {
 irqlevel = 1;
 }
@@ -1014,6 +1017,7 @@ void gicv3_cpuif_update(GICv3CPUState *cs)
 
 qemu_set_irq(cs->parent_fiq, fiqlevel);
 qemu_set_irq(cs->parent_irq, irqlevel);
+qemu_set_irq(cs->parent_nmi, nmilevel);
 }
 
 static uint64_t icc_pmr_read(CPUARMState *env, const ARMCPRegInfo *ri)
-- 
2.34.1




[RFC PATCH v7 17/23] hw/intc/arm_gicv3: Add NMI handling CPU interface registers

2024-03-05 Thread Jinjie Ruan via
Add the NMIAR CPU interface registers which deal with acknowledging NMI.

When introduce NMI interrupt, there are some updates to the semantics for the
register ICC_IAR1_EL1 and ICC_HPPIR1_EL1. For ICC_IAR1_EL1 register, it
should return 1022 if the intid has super priority. And for ICC_NMIAR1_EL1
register, it should return 1023 if the intid do not have super priority.
Howerever, these are not necessary for ICC_HPPIR1_EL1 register.

Signed-off-by: Jinjie Ruan 
Reviewed-by: Richard Henderson 
---
v7:
- Add Reviewed-by.
v4:
- Define ICC_NMIAR1_EL1 only if FEAT_GICv3_NMI is implemented.
- Check sctrl_elx.SCTLR_NMI to return 1022 for icc_iar1_read().
- Add gicv3_icc_nmiar1_read() trace event.
- Do not check icc_hppi_can_preempt() for icc_nmiar1_read().
- Add icv_nmiar1_read() and call it when EL2Enabled() and HCR_EL2.IMO == '1'

Signed-off-by: Jinjie Ruan 
---
 hw/intc/arm_gicv3_cpuif.c | 59 +--
 hw/intc/gicv3_internal.h  |  1 +
 hw/intc/trace-events  |  1 +
 3 files changed, 58 insertions(+), 3 deletions(-)

diff --git a/hw/intc/arm_gicv3_cpuif.c b/hw/intc/arm_gicv3_cpuif.c
index e1a60d8c15..df82a413c6 100644
--- a/hw/intc/arm_gicv3_cpuif.c
+++ b/hw/intc/arm_gicv3_cpuif.c
@@ -795,6 +795,13 @@ static uint64_t icv_iar_read(CPUARMState *env, const 
ARMCPRegInfo *ri)
 return intid;
 }
 
+static uint64_t icv_nmiar1_read(CPUARMState *env, const ARMCPRegInfo *ri)
+{
+/* todo */
+uint64_t intid = INTID_SPURIOUS;
+return intid;
+}
+
 static uint32_t icc_fullprio_mask(GICv3CPUState *cs)
 {
 /*
@@ -1097,7 +1104,8 @@ static uint64_t icc_hppir0_value(GICv3CPUState *cs, 
CPUARMState *env)
 return cs->hppi.irq;
 }
 
-static uint64_t icc_hppir1_value(GICv3CPUState *cs, CPUARMState *env)
+static uint64_t icc_hppir1_value(GICv3CPUState *cs, CPUARMState *env,
+ bool is_nmi, bool is_hppi)
 {
 /* Return the highest priority pending interrupt register value
  * for group 1.
@@ -1108,6 +1116,19 @@ static uint64_t icc_hppir1_value(GICv3CPUState *cs, 
CPUARMState *env)
 return INTID_SPURIOUS;
 }
 
+if (!is_hppi) {
+int el = arm_current_el(env);
+
+if (is_nmi && (!cs->hppi.superprio)) {
+return INTID_SPURIOUS;
+}
+
+if ((!is_nmi) && cs->hppi.superprio
+&& env->cp15.sctlr_el[el] & SCTLR_NMI) {
+return INTID_NMI;
+}
+}
+
 /* Check whether we can return the interrupt or if we should return
  * a special identifier, as per the CheckGroup1ForSpecialIdentifiers
  * pseudocode. (We can simplify a little because for us ICC_SRE_EL1.RM
@@ -1168,7 +1189,7 @@ static uint64_t icc_iar1_read(CPUARMState *env, const 
ARMCPRegInfo *ri)
 if (!icc_hppi_can_preempt(cs)) {
 intid = INTID_SPURIOUS;
 } else {
-intid = icc_hppir1_value(cs, env);
+intid = icc_hppir1_value(cs, env, false, false);
 }
 
 if (!gicv3_intid_is_special(intid)) {
@@ -1179,6 +1200,25 @@ static uint64_t icc_iar1_read(CPUARMState *env, const 
ARMCPRegInfo *ri)
 return intid;
 }
 
+static uint64_t icc_nmiar1_read(CPUARMState *env, const ARMCPRegInfo *ri)
+{
+GICv3CPUState *cs = icc_cs_from_env(env);
+uint64_t intid;
+
+if (icv_access(env, HCR_IMO)) {
+return icv_nmiar1_read(env, ri);
+}
+
+intid = icc_hppir1_value(cs, env, true, false);
+
+if (!gicv3_intid_is_special(intid)) {
+icc_activate_irq(cs, intid);
+}
+
+trace_gicv3_icc_nmiar1_read(gicv3_redist_affid(cs), intid);
+return intid;
+}
+
 static void icc_drop_prio(GICv3CPUState *cs, int grp)
 {
 /* Drop the priority of the currently active interrupt in
@@ -1555,7 +1595,7 @@ static uint64_t icc_hppir1_read(CPUARMState *env, const 
ARMCPRegInfo *ri)
 return icv_hppir_read(env, ri);
 }
 
-value = icc_hppir1_value(cs, env);
+value = icc_hppir1_value(cs, env, false, true);
 trace_gicv3_icc_hppir1_read(gicv3_redist_affid(cs), value);
 return value;
 }
@@ -2482,6 +2522,15 @@ static const ARMCPRegInfo 
gicv3_cpuif_icc_apxr23_reginfo[] = {
 },
 };
 
+static const ARMCPRegInfo gicv3_cpuif_gicv3_nmi_reginfo[] = {
+{ .name = "ICC_NMIAR1_EL1", .state = ARM_CP_STATE_BOTH,
+  .opc0 = 3, .opc1 = 0, .crn = 12, .crm = 9, .opc2 = 5,
+  .type = ARM_CP_IO | ARM_CP_NO_RAW,
+  .access = PL1_R, .accessfn = gicv3_irq_access,
+  .readfn = icc_nmiar1_read,
+},
+};
+
 static uint64_t ich_ap_read(CPUARMState *env, const ARMCPRegInfo *ri)
 {
 GICv3CPUState *cs = icc_cs_from_env(env);
@@ -2838,6 +2887,10 @@ void gicv3_init_cpuif(GICv3State *s)
  */
 define_arm_cp_regs(cpu, gicv3_cpuif_reginfo);
 
+if (s->nmi_support) {
+define_arm_cp_regs(cpu, gicv3_cpuif_gicv3_nmi_reginfo);
+}
+
 /*
  * The CPU implementation specifies the number of supported
  * bits of physical priority. For backwards compatibility
diff --git 

[RFC PATCH v7 06/23] target/arm: Add support for Non-maskable Interrupt

2024-03-05 Thread Jinjie Ruan via
This only implements the external delivery method via the GICv3.

Signed-off-by: Jinjie Ruan 
Reviewed-by: Richard Henderson 
---
v7:
- Add Reviewed-by.
v6:
- env->cp15.hcr_el2 -> arm_hcr_el2_eff().
- env->cp15.hcrx_el2 -> arm_hcrx_el2_eff().
- Not include VF && VFNMI in CPU_INTERRUPT_VNMI.
v4:
- Accept NMI unconditionally for arm_cpu_has_work() but add comment.
- Change from & to && for EXCP_IRQ or EXCP_FIQ.
- Refator nmi mask in arm_excp_unmasked().
- Also handle VNMI in arm_cpu_exec_interrupt() and arm_cpu_set_irq().
- Rename virtual to Virtual.
v3:
- Not include CPU_INTERRUPT_NMI when FEAT_NMI not enabled
- Add ARM_CPU_VNMI.
- Refator nmi mask in arm_excp_unmasked().
- Test SCTLR_ELx.NMI for ALLINT mask for NMI.
---
 target/arm/cpu-qom.h   |  4 +-
 target/arm/cpu.c   | 85 +++---
 target/arm/cpu.h   |  4 ++
 target/arm/helper.c|  2 +
 target/arm/internals.h |  9 +
 5 files changed, 97 insertions(+), 7 deletions(-)

diff --git a/target/arm/cpu-qom.h b/target/arm/cpu-qom.h
index 8e032691db..e0c9e18036 100644
--- a/target/arm/cpu-qom.h
+++ b/target/arm/cpu-qom.h
@@ -36,11 +36,13 @@ DECLARE_CLASS_CHECKERS(AArch64CPUClass, AARCH64_CPU,
 #define ARM_CPU_TYPE_SUFFIX "-" TYPE_ARM_CPU
 #define ARM_CPU_TYPE_NAME(name) (name ARM_CPU_TYPE_SUFFIX)
 
-/* Meanings of the ARMCPU object's four inbound GPIO lines */
+/* Meanings of the ARMCPU object's six inbound GPIO lines */
 #define ARM_CPU_IRQ 0
 #define ARM_CPU_FIQ 1
 #define ARM_CPU_VIRQ 2
 #define ARM_CPU_VFIQ 3
+#define ARM_CPU_NMI 4
+#define ARM_CPU_VNMI 5
 
 /* For M profile, some registers are banked secure vs non-secure;
  * these are represented as a 2-element array where the first element
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
index b2ea5d6513..779e365819 100644
--- a/target/arm/cpu.c
+++ b/target/arm/cpu.c
@@ -122,6 +122,13 @@ void arm_restore_state_to_opc(CPUState *cs,
 }
 #endif /* CONFIG_TCG */
 
+/*
+ * With SCTLR_ELx.NMI == 0, IRQ with Superpriority is masked identically with
+ * IRQ without Superpriority. Moreover, if the GIC is configured so that
+ * FEAT_GICv3_NMI is only set if FEAT_NMI is set, then we won't ever see
+ * CPU_INTERRUPT_*NMI anyway. So we might as well accept NMI here
+ * unconditionally.
+ */
 static bool arm_cpu_has_work(CPUState *cs)
 {
 ARMCPU *cpu = ARM_CPU(cs);
@@ -129,6 +136,7 @@ static bool arm_cpu_has_work(CPUState *cs)
 return (cpu->power_state != PSCI_OFF)
 && cs->interrupt_request &
 (CPU_INTERRUPT_FIQ | CPU_INTERRUPT_HARD
+ | CPU_INTERRUPT_NMI | CPU_INTERRUPT_VNMI
  | CPU_INTERRUPT_VFIQ | CPU_INTERRUPT_VIRQ | CPU_INTERRUPT_VSERR
  | CPU_INTERRUPT_EXITTB);
 }
@@ -668,6 +676,7 @@ static inline bool arm_excp_unmasked(CPUState *cs, unsigned 
int excp_idx,
 CPUARMState *env = cpu_env(cs);
 bool pstate_unmasked;
 bool unmasked = false;
+bool allIntMask = false;
 
 /*
  * Don't take exceptions if they target a lower EL.
@@ -678,13 +687,31 @@ static inline bool arm_excp_unmasked(CPUState *cs, 
unsigned int excp_idx,
 return false;
 }
 
+if (cpu_isar_feature(aa64_nmi, env_archcpu(env)) &&
+env->cp15.sctlr_el[target_el] & SCTLR_NMI && cur_el == target_el) {
+allIntMask = env->pstate & PSTATE_ALLINT ||
+ ((env->cp15.sctlr_el[target_el] & SCTLR_SPINTMASK) &&
+  (env->pstate & PSTATE_SP));
+}
+
 switch (excp_idx) {
+case EXCP_NMI:
+pstate_unmasked = !allIntMask;
+break;
+
+case EXCP_VNMI:
+if ((!(hcr_el2 & HCR_IMO) && !(hcr_el2 & HCR_FMO)) ||
+ (hcr_el2 & HCR_TGE)) {
+/* VNMIs(VIRQs or VFIQs) are only taken when hypervized.  */
+return false;
+}
+return !allIntMask;
 case EXCP_FIQ:
-pstate_unmasked = !(env->daif & PSTATE_F);
+pstate_unmasked = (!(env->daif & PSTATE_F)) && (!allIntMask);
 break;
 
 case EXCP_IRQ:
-pstate_unmasked = !(env->daif & PSTATE_I);
+pstate_unmasked = (!(env->daif & PSTATE_I)) && (!allIntMask);
 break;
 
 case EXCP_VFIQ:
@@ -692,13 +719,13 @@ static inline bool arm_excp_unmasked(CPUState *cs, 
unsigned int excp_idx,
 /* VFIQs are only taken when hypervized.  */
 return false;
 }
-return !(env->daif & PSTATE_F);
+return !(env->daif & PSTATE_F) && (!allIntMask);
 case EXCP_VIRQ:
 if (!(hcr_el2 & HCR_IMO) || (hcr_el2 & HCR_TGE)) {
 /* VIRQs are only taken when hypervized.  */
 return false;
 }
-return !(env->daif & PSTATE_I);
+return !(env->daif & PSTATE_I) && (!allIntMask);
 case EXCP_VSERR:
 if (!(hcr_el2 & HCR_AMO) || (hcr_el2 & HCR_TGE)) {
 /* VIRQs are only taken when hypervized.  */
@@ -804,6 +831,24 @@ static bool arm_cpu_exec_interrupt(CPUState *cs, int 
interrupt_request)
 
 /* The prioritization of interrupts is 

[RFC PATCH v7 22/23] target/arm: Add FEAT_NMI to max

2024-03-05 Thread Jinjie Ruan via
Enable FEAT_NMI on the 'max' CPU.

Signed-off-by: Jinjie Ruan 
Reviewed-by: Richard Henderson 
---
v3:
- Add Reviewed-by.
- Sorted to last.
---
 docs/system/arm/emulation.rst | 1 +
 target/arm/tcg/cpu64.c| 1 +
 2 files changed, 2 insertions(+)

diff --git a/docs/system/arm/emulation.rst b/docs/system/arm/emulation.rst
index f67aea2d83..91baf7ad69 100644
--- a/docs/system/arm/emulation.rst
+++ b/docs/system/arm/emulation.rst
@@ -63,6 +63,7 @@ the following architecture extensions:
 - FEAT_MTE (Memory Tagging Extension)
 - FEAT_MTE2 (Memory Tagging Extension)
 - FEAT_MTE3 (MTE Asymmetric Fault Handling)
+- FEAT_NMI (Non-maskable Interrupt)
 - FEAT_NV (Nested Virtualization)
 - FEAT_NV2 (Enhanced nested virtualization support)
 - FEAT_PACIMP (Pointer authentication - IMPLEMENTATION DEFINED algorithm)
diff --git a/target/arm/tcg/cpu64.c b/target/arm/tcg/cpu64.c
index 5fba2c0f04..60f0dcd799 100644
--- a/target/arm/tcg/cpu64.c
+++ b/target/arm/tcg/cpu64.c
@@ -1175,6 +1175,7 @@ void aarch64_max_tcg_initfn(Object *obj)
 t = FIELD_DP64(t, ID_AA64PFR1, RAS_FRAC, 0);  /* FEAT_RASv1p1 + 
FEAT_DoubleFault */
 t = FIELD_DP64(t, ID_AA64PFR1, SME, 1);   /* FEAT_SME */
 t = FIELD_DP64(t, ID_AA64PFR1, CSV2_FRAC, 0); /* FEAT_CSV2_2 */
+t = FIELD_DP64(t, ID_AA64PFR1, NMI, 1);   /* FEAT_NMI */
 cpu->isar.id_aa64pfr1 = t;
 
 t = cpu->isar.id_aa64mmfr0;
-- 
2.34.1




[RFC PATCH v7 23/23] hw/arm/virt: Add FEAT_GICv3_NMI feature support in virt GIC

2024-03-05 Thread Jinjie Ruan via
A PE that implements FEAT_NMI and FEAT_GICv3 also implements
FEAT_GICv3_NMI. A PE that does not implement FEAT_NMI, does not implement
FEAT_GICv3_NMI

So included support FEAT_GICv3_NMI feature as part of virt platform
GIC initialization if FEAT_NMI and FEAT_GICv3 supported.

Signed-off-by: Jinjie Ruan 
Reviewed-by: Richard Henderson 
---
v4:
- Add Reviewed-by.
v3:
- Adjust to be the last after add FEAT_NMI to max.
- Check whether support FEAT_NMI and FEAT_GICv3 for FEAT_GICv3_NMI.
---
 hw/arm/virt.c | 18 ++
 1 file changed, 18 insertions(+)

diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index 2d4a187fd5..c12307ccd9 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -712,6 +712,19 @@ static void create_v2m(VirtMachineState *vms)
 vms->msi_controller = VIRT_MSI_CTRL_GICV2M;
 }
 
+/*
+ * A PE that implements FEAT_NMI and FEAT_GICv3 also implements
+ * FEAT_GICv3_NMI. A PE that does not implement FEAT_NMI, does not implement
+ * FEAT_GICv3_NMI.
+ */
+static bool gicv3_nmi_present(VirtMachineState *vms)
+{
+ARMCPU *cpu = ARM_CPU(qemu_get_cpu(0));
+
+return cpu_isar_feature(aa64_nmi, cpu) &&
+   (vms->gic_version != VIRT_GIC_VERSION_2);
+}
+
 static void create_gic(VirtMachineState *vms, MemoryRegion *mem)
 {
 MachineState *ms = MACHINE(vms);
@@ -785,6 +798,11 @@ static void create_gic(VirtMachineState *vms, MemoryRegion 
*mem)
   vms->virt);
 }
 }
+
+if (gicv3_nmi_present(vms)) {
+qdev_prop_set_bit(vms->gic, "has-nmi", true);
+}
+
 gicbusdev = SYS_BUS_DEVICE(vms->gic);
 sysbus_realize_and_unref(gicbusdev, _fatal);
 sysbus_mmio_map(gicbusdev, 0, vms->memmap[VIRT_GIC_DIST].base);
-- 
2.34.1




[RFC PATCH v7 14/23] hw/intc/arm_gicv3_redist: Implement GICR_INMIR0

2024-03-05 Thread Jinjie Ruan via
Add GICR_INMIR0 register and support access GICR_INMIR0.

Signed-off-by: Jinjie Ruan 
Reviewed-by: Richard Henderson 
---
v6:
- Add Reviewed-by.
v4:
- Make the GICR_INMIR0 implementation more clearer.
---
 hw/intc/arm_gicv3_redist.c | 19 +++
 hw/intc/gicv3_internal.h   |  1 +
 2 files changed, 20 insertions(+)

diff --git a/hw/intc/arm_gicv3_redist.c b/hw/intc/arm_gicv3_redist.c
index 8153525849..7a16a058b1 100644
--- a/hw/intc/arm_gicv3_redist.c
+++ b/hw/intc/arm_gicv3_redist.c
@@ -35,6 +35,15 @@ static int gicr_ns_access(GICv3CPUState *cs, int irq)
 return extract32(cs->gicr_nsacr, irq * 2, 2);
 }
 
+static void gicr_write_bitmap_reg(GICv3CPUState *cs, MemTxAttrs attrs,
+  uint32_t *reg, uint32_t val)
+{
+/* Helper routine to implement writing to a "set" register */
+val &= mask_group(cs, attrs);
+*reg = val;
+gicv3_redist_update(cs);
+}
+
 static void gicr_write_set_bitmap_reg(GICv3CPUState *cs, MemTxAttrs attrs,
   uint32_t *reg, uint32_t val)
 {
@@ -406,6 +415,10 @@ static MemTxResult gicr_readl(GICv3CPUState *cs, hwaddr 
offset,
 *data = value;
 return MEMTX_OK;
 }
+case GICR_INMIR0:
+*data = cs->gic->nmi_support ?
+gicr_read_bitmap_reg(cs, attrs, cs->gicr_isuperprio) : 0;
+return MEMTX_OK;
 case GICR_ICFGR0:
 case GICR_ICFGR1:
 {
@@ -555,6 +568,12 @@ static MemTxResult gicr_writel(GICv3CPUState *cs, hwaddr 
offset,
 gicv3_redist_update(cs);
 return MEMTX_OK;
 }
+case GICR_INMIR0:
+if (cs->gic->nmi_support) {
+gicr_write_bitmap_reg(cs, attrs, >gicr_isuperprio, value);
+}
+return MEMTX_OK;
+
 case GICR_ICFGR0:
 /* Register is all RAZ/WI or RAO/WI bits */
 return MEMTX_OK;
diff --git a/hw/intc/gicv3_internal.h b/hw/intc/gicv3_internal.h
index 29d5cdc1b6..f35b7d2f03 100644
--- a/hw/intc/gicv3_internal.h
+++ b/hw/intc/gicv3_internal.h
@@ -109,6 +109,7 @@
 #define GICR_ICFGR1   (GICR_SGI_OFFSET + 0x0C04)
 #define GICR_IGRPMODR0(GICR_SGI_OFFSET + 0x0D00)
 #define GICR_NSACR(GICR_SGI_OFFSET + 0x0E00)
+#define GICR_INMIR0   (GICR_SGI_OFFSET + 0x0F80)
 
 /* VLPI redistributor registers, offsets from VLPI_base */
 #define GICR_VPROPBASER   (GICR_VLPI_OFFSET + 0x70)
-- 
2.34.1




[RFC PATCH v7 09/23] target/arm: Handle PSTATE.ALLINT on taking an exception

2024-03-05 Thread Jinjie Ruan via
Set or clear PSTATE.ALLINT on taking an exception to ELx according to the
SCTLR_ELx.SPINTMASK bit.

Signed-off-by: Jinjie Ruan 
Reviewed-by: Richard Henderson 
---
v3:
- Add Reviewed-by.
---
 target/arm/helper.c | 9 +
 1 file changed, 9 insertions(+)

diff --git a/target/arm/helper.c b/target/arm/helper.c
index 15f72fa425..39e76c76ee 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -11540,6 +11540,15 @@ static void arm_cpu_do_interrupt_aarch64(CPUState *cs)
 }
 }
 
+if (cpu_isar_feature(aa64_nmi, cpu) &&
+(env->cp15.sctlr_el[new_el] & SCTLR_NMI)) {
+if (!(env->cp15.sctlr_el[new_el] & SCTLR_SPINTMASK)) {
+new_mode |= PSTATE_ALLINT;
+} else {
+new_mode &= ~PSTATE_ALLINT;
+}
+}
+
 pstate_write(env, PSTATE_DAIF | new_mode);
 env->aarch64 = true;
 aarch64_restore_sp(env, new_el);
-- 
2.34.1




[RFC PATCH v7 10/23] hw/arm/virt: Wire NMI and VNMI irq lines from GIC to CPU

2024-03-05 Thread Jinjie Ruan via
Wire the new NMI and VNMI interrupt line from the GIC to each CPU.

Signed-off-by: Jinjie Ruan 
Reviewed-by: Richard Henderson 
---
v4:
- Add Reviewed-by.
v3:
- Also add VNMI wire.
---
 hw/arm/virt.c | 7 ++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index 0af1943697..2d4a187fd5 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -804,7 +804,8 @@ static void create_gic(VirtMachineState *vms, MemoryRegion 
*mem)
 
 /* Wire the outputs from each CPU's generic timer and the GICv3
  * maintenance interrupt signal to the appropriate GIC PPI inputs,
- * and the GIC's IRQ/FIQ/VIRQ/VFIQ interrupt outputs to the CPU's inputs.
+ * and the GIC's IRQ/FIQ/VIRQ/VFIQ/NMI/VNMI interrupt outputs to the
+ * CPU's inputs.
  */
 for (i = 0; i < smp_cpus; i++) {
 DeviceState *cpudev = DEVICE(qemu_get_cpu(i));
@@ -848,6 +849,10 @@ static void create_gic(VirtMachineState *vms, MemoryRegion 
*mem)
qdev_get_gpio_in(cpudev, ARM_CPU_VIRQ));
 sysbus_connect_irq(gicbusdev, i + 3 * smp_cpus,
qdev_get_gpio_in(cpudev, ARM_CPU_VFIQ));
+sysbus_connect_irq(gicbusdev, i + 4 * smp_cpus,
+   qdev_get_gpio_in(cpudev, ARM_CPU_NMI));
+sysbus_connect_irq(gicbusdev, i + 5 * smp_cpus,
+   qdev_get_gpio_in(cpudev, ARM_CPU_VNMI));
 }
 
 fdt_add_gic_node(vms);
-- 
2.34.1




[RFC PATCH v7 01/23] target/arm: Handle HCR_EL2 accesses for bits introduced with FEAT_NMI

2024-03-05 Thread Jinjie Ruan via
FEAT_NMI defines another three new bits in HCRX_EL2: TALLINT, HCRX_VINMI and
HCRX_VFNMI. When the feature is enabled, allow these bits to be written in
HCRX_EL2.

Signed-off-by: Jinjie Ruan 
Reviewed-by: Richard Henderson 
---
v4:
- Update the comment for FEAT_NMI in hcrx_write().
- Update the commit message, s/thress/three/g.
v3:
- Add Reviewed-by.
- Add HCRX_VINMI and HCRX_VFNMI support in HCRX_EL2.
- Upate the commit messsage.
---
 target/arm/cpu-features.h | 5 +
 target/arm/helper.c   | 5 +
 2 files changed, 10 insertions(+)

diff --git a/target/arm/cpu-features.h b/target/arm/cpu-features.h
index 7567854db6..2ad1179be7 100644
--- a/target/arm/cpu-features.h
+++ b/target/arm/cpu-features.h
@@ -681,6 +681,11 @@ static inline bool isar_feature_aa64_sme(const 
ARMISARegisters *id)
 return FIELD_EX64(id->id_aa64pfr1, ID_AA64PFR1, SME) != 0;
 }
 
+static inline bool isar_feature_aa64_nmi(const ARMISARegisters *id)
+{
+return FIELD_EX64(id->id_aa64pfr1, ID_AA64PFR1, NMI) != 0;
+}
+
 static inline bool isar_feature_aa64_tgran4_lpa2(const ARMISARegisters *id)
 {
 return FIELD_SEX64(id->id_aa64mmfr0, ID_AA64MMFR0, TGRAN4) >= 1;
diff --git a/target/arm/helper.c b/target/arm/helper.c
index 90c4fb72ce..affa493141 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -6056,6 +6056,11 @@ static void hcrx_write(CPUARMState *env, const 
ARMCPRegInfo *ri,
 valid_mask |= HCRX_MSCEN | HCRX_MCE2;
 }
 
+/* FEAT_NMI adds TALLINT, VINMI and VFNMI */
+if (cpu_isar_feature(aa64_nmi, env_archcpu(env))) {
+valid_mask |= HCRX_TALLINT | HCRX_VINMI | HCRX_VFNMI;
+}
+
 /* Clear RES0 bits.  */
 env->cp15.hcrx_el2 = value & valid_mask;
 }
-- 
2.34.1




[RFC PATCH v7 02/23] target/arm: Add PSTATE.ALLINT

2024-03-05 Thread Jinjie Ruan via
When PSTATE.ALLINT is set, an IRQ or FIQ interrupt that is targeted to
ELx, with or without superpriority is masked.

As Richard suggested, place ALLINT bit in PSTATE in env->pstate.

With the change to pstate_read/write, exception entry
and return are automatically handled.

Signed-off-by: Jinjie Ruan 
Reviewed-by: Richard Henderson 
---
v5:
- Remove the ALLINT comment, as it is covered by "all other bits".
- Add Reviewed-by.
v4:
- Keep PSTATE.ALLINT in env->pstate but not env->allint.
- Update the commit message.
v3:
- Remove ALLINT dump in aarch64_cpu_dump_state().
- Update the commit message.
---
 target/arm/cpu.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index a5b3d8f7da..9402d23a93 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -1536,6 +1536,7 @@ FIELD(VTCR, SL2, 33, 1)
 #define PSTATE_D (1U << 9)
 #define PSTATE_BTYPE (3U << 10)
 #define PSTATE_SSBS (1U << 12)
+#define PSTATE_ALLINT (1U << 13)
 #define PSTATE_IL (1U << 20)
 #define PSTATE_SS (1U << 21)
 #define PSTATE_PAN (1U << 22)
-- 
2.34.1




[RFC PATCH v7 21/23] hw/intc/arm_gicv3: Report the VNMI interrupt

2024-03-05 Thread Jinjie Ruan via
In vCPU Interface, if the vIRQ has the superpriority property, report
vNMI to the corresponding vPE.

Signed-off-by: Jinjie Ruan 
Reviewed-by: Richard Henderson 
---
v6:
- Add Reviewed-by.
---
 hw/intc/arm_gicv3_cpuif.c | 14 --
 1 file changed, 12 insertions(+), 2 deletions(-)

diff --git a/hw/intc/arm_gicv3_cpuif.c b/hw/intc/arm_gicv3_cpuif.c
index 483b1bc4a3..f55e8fd277 100644
--- a/hw/intc/arm_gicv3_cpuif.c
+++ b/hw/intc/arm_gicv3_cpuif.c
@@ -465,6 +465,7 @@ void gicv3_cpuif_virt_irq_fiq_update(GICv3CPUState *cs)
 int idx;
 int irqlevel = 0;
 int fiqlevel = 0;
+int nmilevel = 0;
 
 idx = hppvi_index(cs);
 trace_gicv3_cpuif_virt_update(gicv3_redist_affid(cs), idx,
@@ -482,9 +483,17 @@ void gicv3_cpuif_virt_irq_fiq_update(GICv3CPUState *cs)
 uint64_t lr = cs->ich_lr_el2[idx];
 
 if (icv_hppi_can_preempt(cs, lr)) {
-/* Virtual interrupts are simple: G0 are always FIQ, and G1 IRQ */
+/*
+ * Virtual interrupts are simple: G0 are always FIQ, and G1 are
+ * IRQ or NMI which depends on the ICH_LR_EL2.NMI to have
+ * non-maskable property.
+ */
 if (lr & ICH_LR_EL2_GROUP) {
-irqlevel = 1;
+if (cs->gic->nmi_support && (lr & ICH_LR_EL2_NMI)) {
+nmilevel = 1;
+} else {
+irqlevel = 1;
+}
 } else {
 fiqlevel = 1;
 }
@@ -494,6 +503,7 @@ void gicv3_cpuif_virt_irq_fiq_update(GICv3CPUState *cs)
 trace_gicv3_cpuif_virt_set_irqs(gicv3_redist_affid(cs), fiqlevel, 
irqlevel);
 qemu_set_irq(cs->parent_vfiq, fiqlevel);
 qemu_set_irq(cs->parent_virq, irqlevel);
+qemu_set_irq(cs->parent_vnmi, nmilevel);
 }
 
 static void gicv3_cpuif_virt_update(GICv3CPUState *cs)
-- 
2.34.1




[RFC PATCH v7 13/23] hw/intc/arm_gicv3: Add irq superpriority information

2024-03-05 Thread Jinjie Ruan via
A SPI, PPI or SGI interrupt can have a superpriority property. So
maintain superpriority information in PendingIrq and GICR/GICD.

Signed-off-by: Jinjie Ruan 
Acked-by: Richard Henderson 
---
v3:
- Place this ahead of implement GICR_INMIR.
- Add Acked-by.
---
 include/hw/intc/arm_gicv3_common.h | 4 
 1 file changed, 4 insertions(+)

diff --git a/include/hw/intc/arm_gicv3_common.h 
b/include/hw/intc/arm_gicv3_common.h
index 7324c7d983..df4380141d 100644
--- a/include/hw/intc/arm_gicv3_common.h
+++ b/include/hw/intc/arm_gicv3_common.h
@@ -146,6 +146,7 @@ typedef struct {
 int irq;
 uint8_t prio;
 int grp;
+bool superprio;
 } PendingIrq;
 
 struct GICv3CPUState {
@@ -172,6 +173,7 @@ struct GICv3CPUState {
 uint32_t gicr_ienabler0;
 uint32_t gicr_ipendr0;
 uint32_t gicr_iactiver0;
+uint32_t gicr_isuperprio;
 uint32_t edge_trigger; /* ICFGR0 and ICFGR1 even bits */
 uint32_t gicr_igrpmodr0;
 uint32_t gicr_nsacr;
@@ -274,6 +276,7 @@ struct GICv3State {
 GIC_DECLARE_BITMAP(active);   /* GICD_ISACTIVER */
 GIC_DECLARE_BITMAP(level);/* Current level */
 GIC_DECLARE_BITMAP(edge_trigger); /* GICD_ICFGR even bits */
+GIC_DECLARE_BITMAP(superprio);/* GICD_INMIR */
 uint8_t gicd_ipriority[GICV3_MAXIRQ];
 uint64_t gicd_irouter[GICV3_MAXIRQ];
 /* Cached information: pointer to the cpu i/f for the CPUs specified
@@ -313,6 +316,7 @@ GICV3_BITMAP_ACCESSORS(pending)
 GICV3_BITMAP_ACCESSORS(active)
 GICV3_BITMAP_ACCESSORS(level)
 GICV3_BITMAP_ACCESSORS(edge_trigger)
+GICV3_BITMAP_ACCESSORS(superprio)
 
 #define TYPE_ARM_GICV3_COMMON "arm-gicv3-common"
 typedef struct ARMGICv3CommonClass ARMGICv3CommonClass;
-- 
2.34.1




[RFC PATCH v7 18/23] hw/intc/arm_gicv3: Handle icv_nmiar1_read() for icc_nmiar1_read()

2024-03-05 Thread Jinjie Ruan via
Implement icv_nmiar1_read() for icc_nmiar1_read(), so add definition for
ICH_LR_EL2.NMI and ICH_AP1R_EL2.NMI bit.

If FEAT_GICv3_NMI is supported, ich_ap_write() should consider ICH_AP1R_EL2.NMI
bit. In icv_activate_irq() and icv_eoir_write(), the ICH_AP1R_EL2.NMI bit
should be set or clear according to the Superpriority info.

By the way, add gicv3_icv_nmiar1_read trace event.

Signed-off-by: Jinjie Ruan 
Reviewed-by: Richard Henderson 
---
v7:
- Add Reviewed-by.
v6:
- Implement icv_nmiar1_read().
---
 hw/intc/arm_gicv3_cpuif.c | 50 ++-
 hw/intc/gicv3_internal.h  |  3 +++
 hw/intc/trace-events  |  1 +
 3 files changed, 48 insertions(+), 6 deletions(-)

diff --git a/hw/intc/arm_gicv3_cpuif.c b/hw/intc/arm_gicv3_cpuif.c
index df82a413c6..9a7d089dea 100644
--- a/hw/intc/arm_gicv3_cpuif.c
+++ b/hw/intc/arm_gicv3_cpuif.c
@@ -728,7 +728,7 @@ static uint64_t icv_hppir_read(CPUARMState *env, const 
ARMCPRegInfo *ri)
 return value;
 }
 
-static void icv_activate_irq(GICv3CPUState *cs, int idx, int grp)
+static void icv_activate_irq(GICv3CPUState *cs, int idx, int grp, bool nmi)
 {
 /* Activate the interrupt in the specified list register
  * by moving it from Pending to Active state, and update the
@@ -742,7 +742,12 @@ static void icv_activate_irq(GICv3CPUState *cs, int idx, 
int grp)
 
 cs->ich_lr_el2[idx] &= ~ICH_LR_EL2_STATE_PENDING_BIT;
 cs->ich_lr_el2[idx] |= ICH_LR_EL2_STATE_ACTIVE_BIT;
-cs->ich_apr[grp][regno] |= (1 << regbit);
+
+if (cs->gic->nmi_support) {
+cs->ich_apr[grp][regno] |= (1 << regbit) | (nmi ? ICH_AP1R_EL2_NMI : 
0);
+} else {
+cs->ich_apr[grp][regno] |= (1 << regbit);
+}
 }
 
 static void icv_activate_vlpi(GICv3CPUState *cs)
@@ -775,8 +780,8 @@ static uint64_t icv_iar_read(CPUARMState *env, const 
ARMCPRegInfo *ri)
 
 if (thisgrp == grp && icv_hppi_can_preempt(cs, lr)) {
 intid = ich_lr_vintid(lr);
-if (!gicv3_intid_is_special(intid)) {
-icv_activate_irq(cs, idx, grp);
+if (!gicv3_intid_is_special(intid) && !(lr & ICH_LR_EL2_NMI)) {
+icv_activate_irq(cs, idx, grp, false);
 } else {
 /* Interrupt goes from Pending to Invalid */
 cs->ich_lr_el2[idx] &= ~ICH_LR_EL2_STATE_PENDING_BIT;
@@ -797,8 +802,32 @@ static uint64_t icv_iar_read(CPUARMState *env, const 
ARMCPRegInfo *ri)
 
 static uint64_t icv_nmiar1_read(CPUARMState *env, const ARMCPRegInfo *ri)
 {
-/* todo */
+GICv3CPUState *cs = icc_cs_from_env(env);
+int idx = hppvi_index(cs);
 uint64_t intid = INTID_SPURIOUS;
+
+if (idx >= 0 && idx != HPPVI_INDEX_VLPI) {
+uint64_t lr = cs->ich_lr_el2[idx];
+int thisgrp = (lr & ICH_LR_EL2_GROUP) ? GICV3_G1NS : GICV3_G0;
+
+if ((thisgrp == GICV3_G1NS) && (lr & ICH_LR_EL2_NMI)) {
+intid = ich_lr_vintid(lr);
+if (!gicv3_intid_is_special(intid)) {
+icv_activate_irq(cs, idx, GICV3_G1NS, true);
+} else {
+/* Interrupt goes from Pending to Invalid */
+cs->ich_lr_el2[idx] &= ~ICH_LR_EL2_STATE_PENDING_BIT;
+/* We will now return the (bogus) ID from the list register,
+ * as per the pseudocode.
+ */
+}
+}
+}
+
+trace_gicv3_icv_nmiar1_read(gicv3_redist_affid(cs), intid);
+
+gicv3_cpuif_virt_update(cs);
+
 return intid;
 }
 
@@ -1403,6 +1432,11 @@ static int icv_drop_prio(GICv3CPUState *cs)
 return (apr0count + i * 32) << (icv_min_vbpr(cs) + 1);
 } else {
 *papr1 &= *papr1 - 1;
+
+if (cs->gic->nmi_support && (*papr1 & ICH_AP1R_EL2_NMI)) {
+*papr1 &= ~ICH_AP1R_EL2_NMI;
+}
+
 return (apr1count + i * 32) << (icv_min_vbpr(cs) + 1);
 }
 }
@@ -2552,7 +2586,11 @@ static void ich_ap_write(CPUARMState *env, const 
ARMCPRegInfo *ri,
 
 trace_gicv3_ich_ap_write(ri->crm & 1, regno, gicv3_redist_affid(cs), 
value);
 
-cs->ich_apr[grp][regno] = value & 0xU;
+if (cs->gic->nmi_support) {
+cs->ich_apr[grp][regno] = value & (0xU | ICH_AP1R_EL2_NMI);
+} else {
+cs->ich_apr[grp][regno] = value & 0xU;
+}
 gicv3_cpuif_virt_irq_fiq_update(cs);
 }
 
diff --git a/hw/intc/gicv3_internal.h b/hw/intc/gicv3_internal.h
index 93e56b3726..5e2b32861d 100644
--- a/hw/intc/gicv3_internal.h
+++ b/hw/intc/gicv3_internal.h
@@ -242,6 +242,7 @@ FIELD(GICR_VPENDBASER, VALID, 63, 1)
 #define ICH_LR_EL2_PRIORITY_SHIFT 48
 #define ICH_LR_EL2_PRIORITY_LENGTH 8
 #define ICH_LR_EL2_PRIORITY_MASK (0xffULL << ICH_LR_EL2_PRIORITY_SHIFT)
+#define ICH_LR_EL2_NMI (1ULL << 59)
 #define ICH_LR_EL2_GROUP (1ULL << 60)
 #define ICH_LR_EL2_HW (1ULL << 61)
 #define ICH_LR_EL2_STATE_SHIFT 62
@@ -273,6 +274,8 @@ FIELD(GICR_VPENDBASER, VALID, 63, 1)
 #define ICH_VTR_EL2_PREBITS_SHIFT 26
 #define 

[RFC PATCH v7 19/23] hw/intc/arm_gicv3: Implement NMI interrupt prioirty

2024-03-05 Thread Jinjie Ruan via
If GICD_CTLR_DS bit is zero and the NMI is non-secure, the NMI prioirty
is higher than 0x80, otherwise it is higher than 0x0. And save NMI
super prioirty information in hppi.superprio to deliver NMI exception.
Since both GICR and GICD can deliver NMI, it is both necessary to check
whether the pending irq is NMI in gicv3_redist_update_noirqset and
gicv3_update_noirqset. And In irqbetter(), only a non-NMI with the same
priority and a smaller interrupt number can be preempted but not NMI.

Signed-off-by: Jinjie Ruan 
---
v7:
- Reorder the irqbetter() code for clarity.
- Eliminate the has_superprio local variable for gicv3_get_priority().
- false -> cs->hpplpi.superprio in gicv3_redist_update_noirqset().
- 0x0 -> false in arm_gicv3_common_reset_hold().
- Clear superprio in several places for hppi, hpplpi and hppvlpi.
v6:
- Put the "extract superprio info" logic into gicv3_get_priority().
- Update the comment in irqbetter().
- Reset the cs->hppi.superprio to 0x0.
- Set hppi.superprio to false for LPI.
v4:
- Replace is_nmi with has_superprio to not a mix NMI and superpriority.
- Update the comment in irqbetter().
- Extract gicv3_get_priority() to avoid code repeat.
---
v3:
- Add missing brace
---
 hw/intc/arm_gicv3.c| 69 +-
 hw/intc/arm_gicv3_common.c |  3 ++
 hw/intc/arm_gicv3_redist.c |  3 ++
 3 files changed, 66 insertions(+), 9 deletions(-)

diff --git a/hw/intc/arm_gicv3.c b/hw/intc/arm_gicv3.c
index 0b8f79a122..9496a28005 100644
--- a/hw/intc/arm_gicv3.c
+++ b/hw/intc/arm_gicv3.c
@@ -21,7 +21,8 @@
 #include "hw/intc/arm_gicv3.h"
 #include "gicv3_internal.h"
 
-static bool irqbetter(GICv3CPUState *cs, int irq, uint8_t prio)
+static bool irqbetter(GICv3CPUState *cs, int irq, uint8_t prio,
+  bool has_superprio)
 {
 /* Return true if this IRQ at this priority should take
  * precedence over the current recorded highest priority
@@ -30,14 +31,23 @@ static bool irqbetter(GICv3CPUState *cs, int irq, uint8_t 
prio)
  * is the same as this one (a property which the calling code
  * relies on).
  */
-if (prio < cs->hppi.prio) {
-return true;
+if (prio != cs->hppi.prio) {
+return prio < cs->hppi.prio;
+}
+
+/*
+ * The same priority IRQ with superpriority should signal to the CPU
+ * as it have the priority higher than the labelled 0x80 or 0x00.
+ */
+if (has_superprio != cs->hppi.superprio) {
+return has_superprio;
 }
+
 /* If multiple pending interrupts have the same priority then it is an
  * IMPDEF choice which of them to signal to the CPU. We choose to
  * signal the one with the lowest interrupt number.
  */
-if (prio == cs->hppi.prio && irq <= cs->hppi.irq) {
+if (irq <= cs->hppi.irq) {
 return true;
 }
 return false;
@@ -129,6 +139,40 @@ static uint32_t gicr_int_pending(GICv3CPUState *cs)
 return pend;
 }
 
+static bool gicv3_get_priority(GICv3CPUState *cs, bool is_redist,
+   uint8_t *prio, int irq)
+{
+uint32_t superprio = 0x0;
+
+if (is_redist) {
+superprio = extract32(cs->gicr_isuperprio, irq, 1);
+} else {
+superprio = *gic_bmp_ptr32(cs->gic->superprio, irq);
+superprio = superprio & (1 << (irq & 0x1f));
+}
+
+if (superprio) {
+/* DS = 0 & Non-secure NMI */
+if (!(cs->gic->gicd_ctlr & GICD_CTLR_DS) &&
+((is_redist && extract32(cs->gicr_igroupr0, irq, 1)) ||
+ (!is_redist && gicv3_gicd_group_test(cs->gic, irq {
+*prio = 0x80;
+} else {
+*prio = 0x0;
+}
+
+return true;
+}
+
+if (is_redist) {
+*prio = cs->gicr_ipriorityr[irq];
+} else {
+*prio = cs->gic->gicd_ipriority[irq];
+}
+
+return false;
+}
+
 /* Update the interrupt status after state in a redistributor
  * or CPU interface has changed, but don't tell the CPU i/f.
  */
@@ -141,6 +185,7 @@ static void gicv3_redist_update_noirqset(GICv3CPUState *cs)
 uint8_t prio;
 int i;
 uint32_t pend;
+bool has_superprio = false;
 
 /* Find out which redistributor interrupts are eligible to be
  * signaled to the CPU interface.
@@ -152,10 +197,11 @@ static void gicv3_redist_update_noirqset(GICv3CPUState 
*cs)
 if (!(pend & (1 << i))) {
 continue;
 }
-prio = cs->gicr_ipriorityr[i];
-if (irqbetter(cs, i, prio)) {
+has_superprio = gicv3_get_priority(cs, true, , i);
+if (irqbetter(cs, i, prio, has_superprio)) {
 cs->hppi.irq = i;
 cs->hppi.prio = prio;
+cs->hppi.superprio = has_superprio;
 seenbetter = true;
 }
 }
@@ -168,9 +214,11 @@ static void gicv3_redist_update_noirqset(GICv3CPUState *cs)
 if ((cs->gicr_ctlr & GICR_CTLR_ENABLE_LPIS) && cs->gic->lpi_enable &&
 (cs->gic->gicd_ctlr 

[RFC PATCH v7 15/23] hw/intc/arm_gicv3: Implement GICD_INMIR

2024-03-05 Thread Jinjie Ruan via
Add GICD_INMIR, GICD_INMIRnE register and support access GICD_INMIR0.

Signed-off-by: Jinjie Ruan 
Reviewed-by: Richard Henderson 
---
v4:
- Make the GICD_INMIR implementation more clearer.
- Udpate the commit message.
v3:
- Add Reviewed-by.
---
 hw/intc/arm_gicv3_dist.c | 34 ++
 hw/intc/gicv3_internal.h |  2 ++
 2 files changed, 36 insertions(+)

diff --git a/hw/intc/arm_gicv3_dist.c b/hw/intc/arm_gicv3_dist.c
index 35e850685c..9739404e35 100644
--- a/hw/intc/arm_gicv3_dist.c
+++ b/hw/intc/arm_gicv3_dist.c
@@ -89,6 +89,29 @@ static int gicd_ns_access(GICv3State *s, int irq)
 return extract32(s->gicd_nsacr[irq / 16], (irq % 16) * 2, 2);
 }
 
+static void gicd_write_bitmap_reg(GICv3State *s, MemTxAttrs attrs,
+  uint32_t *bmp, maskfn *maskfn,
+  int offset, uint32_t val)
+{
+/*
+ * Helper routine to implement writing to a "set" register
+ * (GICD_INMIR, etc).
+ * Semantics implemented here:
+ * RAZ/WI for SGIs, PPIs, unimplemented IRQs
+ * Bits corresponding to Group 0 or Secure Group 1 interrupts RAZ/WI.
+ * offset should be the offset in bytes of the register from the start
+ * of its group.
+ */
+int irq = offset * 8;
+
+if (irq < GIC_INTERNAL || irq >= s->num_irq) {
+return;
+}
+val &= mask_group_and_nsacr(s, attrs, maskfn, irq);
+*gic_bmp_ptr32(bmp, irq) = val;
+gicv3_update(s, irq, 32);
+}
+
 static void gicd_write_set_bitmap_reg(GICv3State *s, MemTxAttrs attrs,
   uint32_t *bmp,
   maskfn *maskfn,
@@ -543,6 +566,11 @@ static bool gicd_readl(GICv3State *s, hwaddr offset,
 /* RAZ/WI since affinity routing is always enabled */
 *data = 0;
 return true;
+case GICD_INMIR ... GICD_INMIR + 0x7f:
+*data = (!s->nmi_support) ? 0 :
+gicd_read_bitmap_reg(s, attrs, s->superprio, NULL,
+ offset - GICD_INMIR);
+return true;
 case GICD_IROUTER ... GICD_IROUTER + 0x1fdf:
 {
 uint64_t r;
@@ -752,6 +780,12 @@ static bool gicd_writel(GICv3State *s, hwaddr offset,
 case GICD_SPENDSGIR ... GICD_SPENDSGIR + 0xf:
 /* RAZ/WI since affinity routing is always enabled */
 return true;
+case GICD_INMIR ... GICD_INMIR + 0x7f:
+if (s->nmi_support) {
+gicd_write_bitmap_reg(s, attrs, s->superprio, NULL,
+  offset - GICD_INMIR, value);
+}
+return true;
 case GICD_IROUTER ... GICD_IROUTER + 0x1fdf:
 {
 uint64_t r;
diff --git a/hw/intc/gicv3_internal.h b/hw/intc/gicv3_internal.h
index f35b7d2f03..a1fc34597e 100644
--- a/hw/intc/gicv3_internal.h
+++ b/hw/intc/gicv3_internal.h
@@ -52,6 +52,8 @@
 #define GICD_SGIR0x0F00
 #define GICD_CPENDSGIR   0x0F10
 #define GICD_SPENDSGIR   0x0F20
+#define GICD_INMIR   0x0F80
+#define GICD_INMIRnE 0x3B00
 #define GICD_IROUTER 0x6000
 #define GICD_IDREGS  0xFFD0
 
-- 
2.34.1




[RFC PATCH v7 03/23] target/arm: Add support for FEAT_NMI, Non-maskable Interrupt

2024-03-05 Thread Jinjie Ruan via
Add support for FEAT_NMI. NMI (FEAT_NMI) is an mandatory feature in
ARMv8.8-A and ARM v9.3-A.

Signed-off-by: Jinjie Ruan 
Reviewed-by: Richard Henderson 
---
v3:
- Add Reviewed-by.
- Adjust to before the MSR patches.
---
 target/arm/internals.h | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/target/arm/internals.h b/target/arm/internals.h
index 860bcc0c66..980af3c1c1 100644
--- a/target/arm/internals.h
+++ b/target/arm/internals.h
@@ -1078,6 +1078,9 @@ static inline uint32_t aarch64_pstate_valid_mask(const 
ARMISARegisters *id)
 if (isar_feature_aa64_mte(id)) {
 valid |= PSTATE_TCO;
 }
+if (isar_feature_aa64_nmi(id)) {
+valid |= PSTATE_ALLINT;
+}
 
 return valid;
 }
-- 
2.34.1




[RFC PATCH v7 11/23] hw/intc/arm_gicv3: Add external IRQ lines for NMI

2024-03-05 Thread Jinjie Ruan via
Augment the GICv3's QOM device interface by adding one
new set of sysbus IRQ line, to signal NMI to each CPU.

Signed-off-by: Jinjie Ruan 
Reviewed-by: Richard Henderson 
---
v4:
- Add Reviewed-by.
v3:
- Add support for VNMI.
---
 hw/intc/arm_gicv3_common.c | 6 ++
 include/hw/intc/arm_gic_common.h   | 2 ++
 include/hw/intc/arm_gicv3_common.h | 2 ++
 3 files changed, 10 insertions(+)

diff --git a/hw/intc/arm_gicv3_common.c b/hw/intc/arm_gicv3_common.c
index cb55c72681..c52f060026 100644
--- a/hw/intc/arm_gicv3_common.c
+++ b/hw/intc/arm_gicv3_common.c
@@ -299,6 +299,12 @@ void gicv3_init_irqs_and_mmio(GICv3State *s, 
qemu_irq_handler handler,
 for (i = 0; i < s->num_cpu; i++) {
 sysbus_init_irq(sbd, >cpu[i].parent_vfiq);
 }
+for (i = 0; i < s->num_cpu; i++) {
+sysbus_init_irq(sbd, >cpu[i].parent_nmi);
+}
+for (i = 0; i < s->num_cpu; i++) {
+sysbus_init_irq(sbd, >cpu[i].parent_vnmi);
+}
 
 memory_region_init_io(>iomem_dist, OBJECT(s), ops, s,
   "gicv3_dist", 0x1);
diff --git a/include/hw/intc/arm_gic_common.h b/include/hw/intc/arm_gic_common.h
index 7080375008..97fea4102d 100644
--- a/include/hw/intc/arm_gic_common.h
+++ b/include/hw/intc/arm_gic_common.h
@@ -71,6 +71,8 @@ struct GICState {
 qemu_irq parent_fiq[GIC_NCPU];
 qemu_irq parent_virq[GIC_NCPU];
 qemu_irq parent_vfiq[GIC_NCPU];
+qemu_irq parent_nmi[GIC_NCPU];
+qemu_irq parent_vnmi[GIC_NCPU];
 qemu_irq maintenance_irq[GIC_NCPU];
 
 /* GICD_CTLR; for a GIC with the security extensions the NS banked version
diff --git a/include/hw/intc/arm_gicv3_common.h 
b/include/hw/intc/arm_gicv3_common.h
index 4e2fb518e7..7324c7d983 100644
--- a/include/hw/intc/arm_gicv3_common.h
+++ b/include/hw/intc/arm_gicv3_common.h
@@ -155,6 +155,8 @@ struct GICv3CPUState {
 qemu_irq parent_fiq;
 qemu_irq parent_virq;
 qemu_irq parent_vfiq;
+qemu_irq parent_nmi;
+qemu_irq parent_vnmi;
 
 /* Redistributor */
 uint32_t level;  /* Current IRQ level */
-- 
2.34.1




Re: [External] Re: [PATCH v1 1/1] memory tier: acpi/hmat: create CPUless memory tiers after obtaining HMAT info

2024-03-05 Thread Ho-Ren (Jack) Chuang
On Tue, Mar 5, 2024 at 6:27 PM Huang, Ying  wrote:
>
> "Ho-Ren (Jack) Chuang"  writes:
>
> > On Sun, Mar 3, 2024 at 6:42 PM Huang, Ying  wrote:
> >>
> >> Hi, Jack,
> >>
> >> "Ho-Ren (Jack) Chuang"  writes:
> >>
> >> > * Introduce `mt_init_with_hmat()`
> >> > We defer memory tier initialization for those CPUless NUMA nodes
> >> > until acquiring HMAT info. `mt_init_with_hmat()` is introduced to
> >> > post-create CPUless memory tiers after obtaining HMAT info.
> >> > It iterates through each CPUless memory node, creating memory tiers if
> >> > necessary. Finally, it calculates demotion tables again at the end.
> >> >
> >> > * Introduce `hmat_find_alloc_memory_type()`
> >> > Find or allocate a memory type in the `hmat_memory_types` list.
> >> >
> >> > * Make `set_node_memory_tier()` more generic
> >> > This function can also be used for setting other memory types for a node.
> >> > To do so, a new argument is added to specify a memory type.
> >> >
> >> > * Handle cases where there is no HMAT when creating memory tiers
> >> > If no HMAT is specified, it falls back to using `default_dram_type`.
> >> >
> >> > * Change adist calculation code to use another new lock, mt_perf_lock.
> >> > Iterating through CPUlist nodes requires holding the `memory_tier_lock`.
> >> > However, `mt_calc_adistance()` will end up trying to acquire the same 
> >> > lock,
> >> > leading to a potential deadlock. Therefore, we propose introducing a
> >> > standalone `mt_perf_lock` to protect `default_dram_perf`. This approach 
> >> > not
> >> > only avoids deadlock but also prevents holding a large lock 
> >> > simultaneously.
> >>
> >> The patch description is used to described why we need the change, and
> >> how we do that, but not what we do.  People can tell what is done from
> >> the code itself.
> >>
> >
> > Got it. Thanks. Will rewrite it after the code is finalized.
> >
> >> > Signed-off-by: Ho-Ren (Jack) Chuang 
> >> > Signed-off-by: Hao Xiang 
> >> > ---
> >> >  drivers/acpi/numa/hmat.c |  3 ++
> >> >  include/linux/memory-tiers.h |  6 +++
> >> >  mm/memory-tiers.c| 76 
> >> >  3 files changed, 77 insertions(+), 8 deletions(-)
> >> >
> >> > diff --git a/drivers/acpi/numa/hmat.c b/drivers/acpi/numa/hmat.c
> >> > index d6b85f0f6082..9f57338b3cb5 100644
> >> > --- a/drivers/acpi/numa/hmat.c
> >> > +++ b/drivers/acpi/numa/hmat.c
> >> > @@ -1038,6 +1038,9 @@ static __init int hmat_init(void)
> >> >   if (!hmat_set_default_dram_perf())
> >> >   register_mt_adistance_algorithm(_adist_nb);
> >> >
> >> > + /* Post-create CPUless memory tiers after getting HMAT info */
> >> > + mt_init_with_hmat();
> >> > +
> >> >   return 0;
> >> >  out_put:
> >> >   hmat_free_structures();
> >> > diff --git a/include/linux/memory-tiers.h b/include/linux/memory-tiers.h
> >> > index 69e781900082..2f845e90c033 100644
> >> > --- a/include/linux/memory-tiers.h
> >> > +++ b/include/linux/memory-tiers.h
> >> > @@ -48,6 +48,7 @@ int mt_calc_adistance(int node, int *adist);
> >> >  int mt_set_default_dram_perf(int nid, struct access_coordinate *perf,
> >> >const char *source);
> >> >  int mt_perf_to_adistance(struct access_coordinate *perf, int *adist);
> >> > +void mt_init_with_hmat(void);
> >>
> >> HMAT isn't universally available.  It's a driver in fact.  So, don't put
> >> driver specific code in general code.
> >>
> >
> > Please see below regarding "move code to hmat.c"
> >
> >> >  #ifdef CONFIG_MIGRATION
> >> >  int next_demotion_node(int node);
> >> >  void node_get_allowed_targets(pg_data_t *pgdat, nodemask_t *targets);
> >> > @@ -136,5 +137,10 @@ static inline int mt_perf_to_adistance(struct 
> >> > access_coordinate *perf, int *adis
> >> >  {
> >> >   return -EIO;
> >> >  }
> >> > +
> >> > +static inline void mt_init_with_hmat(void)
> >> > +{
> >> > +
> >> > +}
> >> >  #endif   /* CONFIG_NUMA */
> >> >  #endif  /* _LINUX_MEMORY_TIERS_H */
> >> > diff --git a/mm/memory-tiers.c b/mm/memory-tiers.c
> >> > index 0537664620e5..7a0a579b3deb 100644
> >> > --- a/mm/memory-tiers.c
> >> > +++ b/mm/memory-tiers.c
> >> > @@ -35,7 +35,9 @@ struct node_memory_type_map {
> >> >  };
> >> >
> >> >  static DEFINE_MUTEX(memory_tier_lock);
> >> > +static DEFINE_MUTEX(mt_perf_lock);
> >> >  static LIST_HEAD(memory_tiers);
> >> > +static LIST_HEAD(hmat_memory_types);
> >> >  static struct node_memory_type_map node_memory_types[MAX_NUMNODES];
> >> >  struct memory_dev_type *default_dram_type;
> >> >
> >> > @@ -502,7 +504,7 @@ static inline void __init_node_memory_type(int node, 
> >> > struct memory_dev_type *mem
> >> >   }
> >> >  }
> >> >
> >> > -static struct memory_tier *set_node_memory_tier(int node)
> >> > +static struct memory_tier *set_node_memory_tier(int node, struct 
> >> > memory_dev_type *new_memtype)
> >>
> >> No. memory_dev_type are passed to the function via 
> >> node_memory_types[node].memtype.
> >>
> >
> > Got it. Will mimic the way 

Re: [PATCH V2 1/1] target/loongarch: Fixed tlb huge page loading issue

2024-03-05 Thread lixianglai

Hi Richard :

On 3/4/24 20:21, lixianglai wrote:

Hi Richard:

On 3/4/24 17:51, Xianglai Li wrote:

When we use qemu tcg simulation, the page size of bios is 4KB.
When using the level 2 super large page (page size is 1G) to create 
the page table,
it is found that the content of the corresponding address space is 
abnormal,
resulting in the bios can not start the operating system and 
graphical interface normally.


The lddir and ldpte instruction emulation has
a problem with the use of super large page processing above level 2.
The page size is not correctly calculated,
resulting in the wrong page size of the table entry found by tlb.

Signed-off-by: Xianglai Li 
Cc: maob...@loongson.cn
Cc: Song Gao 
Cc: Xiaojuan Yang 
Cc: zhaotian...@loongson.cn
---
  target/loongarch/cpu.h    |  1 +
  target/loongarch/tcg/tlb_helper.c | 21 -
  2 files changed, 13 insertions(+), 9 deletions(-)

diff --git a/target/loongarch/cpu.h b/target/loongarch/cpu.h
index ec37579fd6..eab3e41c71 100644
--- a/target/loongarch/cpu.h
+++ b/target/loongarch/cpu.h
@@ -292,6 +292,7 @@ typedef struct CPUArchState {
  uint32_t fcsr0_mask;
    uint32_t cpucfg[21];
+    uint32_t lddir_ps;


This magical cpu state does not appear in the manual.


The hardware instruction manual is hosted on github at

https://github.com/loongson/LoongArch-Documentation

Are you sure that large pages above level 2 are really supported by 
LDDIR?



Yes,We have done tests on the physical cpu of loongarch64 and

it works fine with a level 2 large page on the physical cpu.




Some explanation from the hardware engineering side is required.


The description of lddir hardware manual is as follows:


Instruction formats:

|lddir rd, rj, level|

The|LDDIR|instruction is used for accessing directory entries during 
software page table walking.


If bit|[6]|of the general register|rj|is|0|, it means that the 
content of|rj|is the physical address of the


base address of the level page table at this time. In this case, 
the|LDDIR|instruction will access the level


page table according to the current TLB refill address, retrieve the 
base address of the corresponding


|level+1|page table, and write it to the general register|rd|.


reference:

https://loongson.github.io/LoongArch-Documentation/LoongArch-Vol1-EN.html 




  4.2.5.1.|LDDIR|


Yes, I have this manual.  Please highlight the portion of this 
description that corresponds to the LDDIR_PS variable that you add.




Sorry, I don't think I quite understand what you mean.

Do you mean that you want me to point out the detailed description of 
LDDIR_PS in the manual


or suggest that I add a corresponding comment to the LDDIR_PS variable 
in the patch?



I think the description I quoted is missing a key part:

If bit|[6]|of general register|rj|is|1|, it means that the content 
in|rj|is a large page (Huge Page) page table entry. In this case, after 
executing the|LDDRI|instruction, the value in the general 
register|rj|will be written directly to the general register|rd|.


The LDDIR_PS variable is not described in detail in the manual, but is 
only an intermediate variable to assist in page size calculation during 
tcg simulation.


However, in section 5.4.2 TLB, we learned that TLB is divided into STLB 
and MTLB.


The PS field in MTLB has the same meaning as the variable LDDIR_PS we 
defined.


Since TLB is divided into parity entries, Therefore, when the TLB is 
generated,


the size of each parity entry becomes half, that is, LDDIR_PS-1.

It should be noted here that all large-page tlb entries will be placed 
in the MTLB, because the PS field is only meaningful in the MTLB.



Thanks,

Xianglai.






r~


Re: [PATCH v3 0/2] Export debug triggers as an extension

2024-03-05 Thread Alistair Francis
On Fri, Mar 1, 2024 at 2:20 AM Anup Patel  wrote:
>
> On Thu, Feb 29, 2024 at 8:42 PM Andrew Jones  wrote:
> >
> > On Thu, Feb 29, 2024 at 07:07:43PM +0530, Himanshu Chauhan wrote:
> > > All the CPUs may or may not implement the debug triggers (sdtrig)
> > > extension. The presence of it should be dynamically detectable.
> > > This patch exports the debug triggers as an extension which
> > > can be turned on or off by sdtrig= option. It is
> > > turned on by default.
> > >
> > > "sdtrig" is concatenated to ISA string when it is enabled.
> > > Like so:
> > > rv64imafdch_zicbom_*_sdtrig_*_sstc_svadu
> > >
> > > Changes from v1:
> > >- Replaced the debug property with ext_sdtrig
> > >- Marked it experimenatal by naming it x-sdtrig
> > >- x-sdtrig is added to ISA string
> > >- Reversed the patch order
> > >
> > > Changes from v2:
> > >- Mark debug property as deprecated and replace internally with sdtrig 
> > > extension
> >
> > I'm getting lost in our discussions, but I thought we needed both in case
> > a machine only implements debug 0.13, since sdtrig is at least 'more than'
> > debug, even if backwards compatible (which I also wasn't sure was the
> > case). If, OTOH, QEMU's debug implementation exactly implements sdtrig's
> > specification, then I'm in favor of deprecating the 'debug' extension.
>
> The QEMU's debug implementation aligns more with Sdtrig v1.0 specification
> because we have mcontrol6 which was not present in debug 0.13

I'm not sure that's exactly the case. I think QEMU implements the
debug 0.13 specification and also the mcontrol6. That's really a bug
that we support mcontrol6, it snuck in.

We can just support both and wrap the mcontrol6 section behind a
sdtrig check. That seems to be the easiest option. That way we can
support the current ratified debug spec and the experimental soon to
be ratified sdtrig and friends spec.

Alistair

>
> IMO, we should definitely depricate debug 0.13
>
> Regards,
> Anup
>
> >
> > Thanks,
> > drew
> >
> >
> > >- setting/unsetting debug property shows warning and sets/unsets 
> > > ext_sdtrig
> > >- sdtrig is added to ISA string as RISC-V debug specification is frozen
> > >
> > > Himanshu Chauhan (2):
> > >   target/riscv: Mark debug property as deprecated
> > >   target/riscv: Export sdtrig in ISA string
> > >
> > >  target/riscv/cpu.c| 38 +++---
> > >  target/riscv/cpu_cfg.h|  2 +-
> > >  target/riscv/cpu_helper.c |  2 +-
> > >  target/riscv/csr.c|  2 +-
> > >  target/riscv/machine.c|  2 +-
> > >  5 files changed, 39 insertions(+), 7 deletions(-)
> > >
> > > --
> > > 2.34.1
> > >
> > >
> >
>



RE: [PATCH v6 8/9] hw/arm/virt: Set virtio-iommu aw-bits default value to 48

2024-03-05 Thread Duan, Zhenzhong



>-Original Message-
>From: Eric Auger 
>Subject: [PATCH v6 8/9] hw/arm/virt: Set virtio-iommu aw-bits default value
>to 48
>
>On ARM we set 48b as a default (matching SMMUv3 SMMU_IDR5.VAX == 0).
>
>hw_compat_8_2 is used to handle the compatibility for machine types
>before 9.0 (default was 64 bits).
>
>Signed-off-by: Eric Auger 
>---
> hw/arm/virt.c | 17 +
> 1 file changed, 17 insertions(+)
>
>diff --git a/hw/arm/virt.c b/hw/arm/virt.c
>index 0af1943697..dcfb25369b 100644
>--- a/hw/arm/virt.c
>+++ b/hw/arm/virt.c
>@@ -85,11 +85,28 @@
> #include "hw/char/pl011.h"
> #include "qemu/guest-random.h"
>
>+GlobalProperty arm_virt_compat[] = {
>+{ TYPE_VIRTIO_IOMMU_PCI, "aw-bits", "48" },
>+};
>+const size_t arm_virt_compat_len = G_N_ELEMENTS(arm_virt_compat);

This can be static, otherwise,

Reviewed-by: Zhenzhong Duan 

Thanks
Zhenzhong

>+
>+/*
>+ * This cannot be called from the virt_machine_class_init() because
>+ * TYPE_VIRT_MACHINE is abstract and mc->compat_props
>g_ptr_array_new()
>+ * only is called on virt non abstract class init.
>+ */
>+static void arm_virt_compat_set(MachineClass *mc)
>+{
>+compat_props_add(mc->compat_props, arm_virt_compat,
>+ arm_virt_compat_len);
>+}
>+
> #define DEFINE_VIRT_MACHINE_LATEST(major, minor, latest) \
> static void virt_##major##_##minor##_class_init(ObjectClass *oc, \
> void *data) \
> { \
> MachineClass *mc = MACHINE_CLASS(oc); \
>+arm_virt_compat_set(mc); \
> virt_machine_##major##_##minor##_options(mc); \
> mc->desc = "QEMU " # major "." # minor " ARM Virtual Machine"; \
> if (latest) { \
>--
>2.41.0




Re: [PATCH] hw/core/machine-smp: Remove deprecated "parameter=0" SMP configurations

2024-03-05 Thread Zhao Liu
Hi Prasad,

> On Tue, 5 Mar 2024 at 12:59, Zhao Liu  wrote:
> > After simple test, if user sets maxcpus as 0, the has_maxcpus will be
> > true as well...I think it's related with QAPI code generation logic.
> 
> * Right.
> 
> [Maybe we digressed a bit in the discussion, so I snipped much of the
> details here. Sorry about that.]
> 
> * "if user sets maxcpus as 0, the has_maxcpus will be true as well",
> ie if 'has_*' fields are always set
> 
> unsigned maxcpus = config->has_maxcpus ? config->maxcpus : 0;
> 
> then checking 'config->has_maxcpus ?' above is probably not required I
> think. It could just be
> 
>maxcpus = config->maxcpus

Yes.

> If a user does not specify config->maxcpus with -smp option, then it
> could default to zero(0) in 'config' parameter? (same for other config
> fields)
 
Yes. I could post another series for this cleanup soon.

> * If such change requires API changes (I'm not sure how), then
> probably it is outside the scope of this patch.
> 
> ...wdyt?
>

The above change you suggested doesn't require API changes ;-).

Thanks,
Zhao




RE: [PATCH v6 7/9] hw/i386/q35: Set virtio-iommu aw-bits default value to 39

2024-03-05 Thread Duan, Zhenzhong
Hi Eric,

>-Original Message-
>From: Eric Auger 
>Subject: [PATCH v6 7/9] hw/i386/q35: Set virtio-iommu aw-bits default
>value to 39
>
>Currently the default input range can extend to 64 bits. On x86,
>when the virtio-iommu protects vfio devices, the physical iommu
>may support only 39 bits. Let's set the default to 39, as done
>for the intel-iommu.
>
>We use hw_compat_8_2 to handle the compatibility for machines
>before 9.0 which used to have a virtio-iommu default input range
>of 64 bits.
>
>Of course if aw-bits is set from the command line, the default
>is overriden.
>
>Signed-off-by: Eric Auger 
>
>---
>
>v5 -> v6:
>- split pc/arm settings
>
>v3 -> v4:
>- update the qos test to relax the check on the max input IOVA
>
>v2 -> v3:
>- collected Zhenzhong's R-b
>- use _abort instead of NULL error handle
>  on object_property_get_uint() call (Cédric)
>- use VTD_HOST_AW_39BIT (Cédric)
>
>v1 -> v2:
>- set aw-bits to 48b on ARM
>- use hw_compat_8_2 to handle the compat for older machines
>  which used 64b as a default
>---
> include/hw/i386/pc.h| 3 +++
> hw/core/machine.c   | 1 +
> hw/i386/pc.c| 6 ++
> hw/i386/pc_q35.c| 2 ++
> tests/qtest/virtio-iommu-test.c | 2 +-
> 5 files changed, 13 insertions(+), 1 deletion(-)
>
>diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h
>index 5065590281..b3229f98de 100644
>--- a/include/hw/i386/pc.h
>+++ b/include/hw/i386/pc.h
>@@ -198,6 +198,9 @@ void pc_system_parse_ovmf_flash(uint8_t
>*flash_ptr, size_t flash_size);
> /* sgx.c */
> void pc_machine_init_sgx_epc(PCMachineState *pcms);
>
>+extern GlobalProperty pc_compat_defaults[];
>+extern const size_t pc_compat_defaults_len;

If we only want to support q35 and not i440fx, better to add _q35 suffix and 
move into pc_q35.c and made static?

>+
> extern GlobalProperty pc_compat_8_2[];
> extern const size_t pc_compat_8_2_len;
>
>diff --git a/hw/core/machine.c b/hw/core/machine.c
>index 6bd09d4592..4b89172d1c 100644
>--- a/hw/core/machine.c
>+++ b/hw/core/machine.c
>@@ -35,6 +35,7 @@
>
> GlobalProperty hw_compat_8_2[] = {
> { TYPE_VIRTIO_IOMMU_PCI, "granule", "4k" },
>+{ TYPE_VIRTIO_IOMMU_PCI, "aw-bits", "64" },
> };
> const size_t hw_compat_8_2_len = G_N_ELEMENTS(hw_compat_8_2);
>
>diff --git a/hw/i386/pc.c b/hw/i386/pc.c
>index f5ff970acf..9024483356 100644
>--- a/hw/i386/pc.c
>+++ b/hw/i386/pc.c
>@@ -59,6 +59,7 @@
> #include "hw/i386/kvm/xen_evtchn.h"
> #include "hw/i386/kvm/xen_gnttab.h"
> #include "hw/i386/kvm/xen_xenstore.h"
>+#include "hw/i386/intel_iommu.h"

This can be removed?

> #include "hw/mem/memory-device.h"
> #include "e820_memory_layout.h"
> #include "trace.h"
>@@ -78,6 +79,11 @@
> { "qemu64-" TYPE_X86_CPU, "model-id", "QEMU Virtual CPU version "
>v, },\
> { "athlon-" TYPE_X86_CPU, "model-id", "QEMU Virtual CPU version " v, },
>
>+GlobalProperty pc_compat_defaults[] =  {
>+{ TYPE_VIRTIO_IOMMU_PCI, "aw-bits", "39" },
>+};
>+const size_t pc_compat_defaults_len =
>G_N_ELEMENTS(pc_compat_defaults);
>+
> GlobalProperty pc_compat_8_2[] = {};
> const size_t pc_compat_8_2_len = G_N_ELEMENTS(pc_compat_8_2);
>
>diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c
>index 45a4102e75..32421a0a5f 100644
>--- a/hw/i386/pc_q35.c
>+++ b/hw/i386/pc_q35.c
>@@ -356,6 +356,8 @@ static void pc_q35_machine_options(MachineClass
>*m)
> machine_class_allow_dynamic_sysbus_dev(m,
>TYPE_INTEL_IOMMU_DEVICE);
> machine_class_allow_dynamic_sysbus_dev(m, TYPE_RAMFB_DEVICE);
> machine_class_allow_dynamic_sysbus_dev(m, TYPE_VMBUS_BRIDGE);
>+compat_props_add(m->compat_props,
>+ pc_compat_defaults, pc_compat_defaults_len);
> }
>
> static void pc_q35_9_0_machine_options(MachineClass *m)
>diff --git a/tests/qtest/virtio-iommu-test.c b/tests/qtest/virtio-iommu-test.c
>index 068e7a9e6c..0f36381acb 100644
>--- a/tests/qtest/virtio-iommu-test.c
>+++ b/tests/qtest/virtio-iommu-test.c
>@@ -34,7 +34,7 @@ static void pci_config(void *obj, void *data,
>QGuestAllocator *t_alloc)
> uint8_t bypass = qvirtio_config_readb(dev, 36);
>
> g_assert_cmpint(input_range_start, ==, 0);
>-g_assert_cmphex(input_range_end, ==, UINT64_MAX);
>+g_assert_cmphex(input_range_end, >=, 32);

UINT32_MAX?

Thanks
Zhenzhong

> g_assert_cmpint(domain_range_start, ==, 0);
> g_assert_cmpint(domain_range_end, ==, UINT32_MAX);
> g_assert_cmpint(bypass, ==, 1);
>--
>2.41.0



Re: [PATCH 0/2] target/riscv/kvm: update KVM exts to Linux 6.8

2024-03-05 Thread Alistair Francis
On Mon, Mar 4, 2024 at 11:48 PM Daniel Henrique Barboza
 wrote:
>
> Hi,
>
> Let's update QEMU KVM extension support up to 6.8-rc6 before the 9.0
> freeze.
>
> Patches based on alistair/riscv-to-apply.next.
>
> Daniel Henrique Barboza (2):
>   linux-headers: Update to Linux v6.8-rc6
>   target/riscv/kvm: update KVM exts to Linux 6.8

Thanks!

Applied to riscv-to-apply.next

Alistair

>
>  include/standard-headers/drm/drm_fourcc.h |  10 +-
>  include/standard-headers/linux/ethtool.h  |  41 +++--
>  .../standard-headers/linux/virtio_config.h|   8 +-
>  include/standard-headers/linux/virtio_pci.h   |  68 +
>  include/standard-headers/linux/virtio_pmem.h  |   7 +
>  linux-headers/asm-generic/unistd.h|  15 +-
>  linux-headers/asm-mips/mman.h |   2 +-
>  linux-headers/asm-mips/unistd_n32.h   |   5 +
>  linux-headers/asm-mips/unistd_n64.h   |   5 +
>  linux-headers/asm-mips/unistd_o32.h   |   5 +
>  linux-headers/asm-powerpc/unistd_32.h |   5 +
>  linux-headers/asm-powerpc/unistd_64.h |   5 +
>  linux-headers/asm-riscv/kvm.h |  40 +
>  linux-headers/asm-s390/unistd_32.h|   5 +
>  linux-headers/asm-s390/unistd_64.h|   5 +
>  linux-headers/asm-x86/kvm.h   |   3 +
>  linux-headers/asm-x86/unistd_32.h |   5 +
>  linux-headers/asm-x86/unistd_64.h |   5 +
>  linux-headers/asm-x86/unistd_x32.h|   5 +
>  linux-headers/linux/iommufd.h |  79 ++
>  linux-headers/linux/kvm.h | 140 +++---
>  linux-headers/linux/userfaultfd.h |  29 +++-
>  linux-headers/linux/vfio.h|   1 +
>  target/riscv/kvm/kvm-cpu.c|  29 
>  24 files changed, 410 insertions(+), 112 deletions(-)
>
> --
> 2.43.2
>
>



Re: [PATCH 2/2] target/riscv/kvm: update KVM exts to Linux 6.8

2024-03-05 Thread Alistair Francis
On Mon, Mar 4, 2024 at 11:48 PM Daniel Henrique Barboza
 wrote:
>
> The last KVM extensions added were back in 6.6. Sync them to Linux 6.8.
>
> Signed-off-by: Daniel Henrique Barboza 

Acked-by: Alistair Francis 

Alistair

> ---
>  target/riscv/kvm/kvm-cpu.c | 29 +
>  1 file changed, 29 insertions(+)
>
> diff --git a/target/riscv/kvm/kvm-cpu.c b/target/riscv/kvm/kvm-cpu.c
> index 422e4f121c..c7afdb1e81 100644
> --- a/target/riscv/kvm/kvm-cpu.c
> +++ b/target/riscv/kvm/kvm-cpu.c
> @@ -275,13 +275,42 @@ static KVMCPUConfig kvm_multi_ext_cfgs[] = {
>  KVM_EXT_CFG("zicbom", ext_zicbom, KVM_RISCV_ISA_EXT_ZICBOM),
>  KVM_EXT_CFG("zicboz", ext_zicboz, KVM_RISCV_ISA_EXT_ZICBOZ),
>  KVM_EXT_CFG("zicntr", ext_zicntr, KVM_RISCV_ISA_EXT_ZICNTR),
> +KVM_EXT_CFG("zicond", ext_zicond, KVM_RISCV_ISA_EXT_ZICOND),
>  KVM_EXT_CFG("zicsr", ext_zicsr, KVM_RISCV_ISA_EXT_ZICSR),
>  KVM_EXT_CFG("zifencei", ext_zifencei, KVM_RISCV_ISA_EXT_ZIFENCEI),
> +KVM_EXT_CFG("zihintntl", ext_zihintntl, KVM_RISCV_ISA_EXT_ZIHINTNTL),
>  KVM_EXT_CFG("zihintpause", ext_zihintpause, 
> KVM_RISCV_ISA_EXT_ZIHINTPAUSE),
>  KVM_EXT_CFG("zihpm", ext_zihpm, KVM_RISCV_ISA_EXT_ZIHPM),
> +KVM_EXT_CFG("zfa", ext_zfa, KVM_RISCV_ISA_EXT_ZFA),
> +KVM_EXT_CFG("zfh", ext_zfh, KVM_RISCV_ISA_EXT_ZFH),
> +KVM_EXT_CFG("zfhmin", ext_zfhmin, KVM_RISCV_ISA_EXT_ZFHMIN),
>  KVM_EXT_CFG("zba", ext_zba, KVM_RISCV_ISA_EXT_ZBA),
>  KVM_EXT_CFG("zbb", ext_zbb, KVM_RISCV_ISA_EXT_ZBB),
> +KVM_EXT_CFG("zbc", ext_zbc, KVM_RISCV_ISA_EXT_ZBC),
> +KVM_EXT_CFG("zbkb", ext_zbkb, KVM_RISCV_ISA_EXT_ZBKB),
> +KVM_EXT_CFG("zbkc", ext_zbkc, KVM_RISCV_ISA_EXT_ZBKC),
> +KVM_EXT_CFG("zbkx", ext_zbkx, KVM_RISCV_ISA_EXT_ZBKX),
>  KVM_EXT_CFG("zbs", ext_zbs, KVM_RISCV_ISA_EXT_ZBS),
> +KVM_EXT_CFG("zknd", ext_zknd, KVM_RISCV_ISA_EXT_ZKND),
> +KVM_EXT_CFG("zkne", ext_zkne, KVM_RISCV_ISA_EXT_ZKNE),
> +KVM_EXT_CFG("zknh", ext_zknh, KVM_RISCV_ISA_EXT_ZKNH),
> +KVM_EXT_CFG("zkr", ext_zkr, KVM_RISCV_ISA_EXT_ZKR),
> +KVM_EXT_CFG("zksed", ext_zksed, KVM_RISCV_ISA_EXT_ZKSED),
> +KVM_EXT_CFG("zksh", ext_zksh, KVM_RISCV_ISA_EXT_ZKSH),
> +KVM_EXT_CFG("zkt", ext_zkt, KVM_RISCV_ISA_EXT_ZKT),
> +KVM_EXT_CFG("zvbb", ext_zvbb, KVM_RISCV_ISA_EXT_ZVBB),
> +KVM_EXT_CFG("zvbc", ext_zvbc, KVM_RISCV_ISA_EXT_ZVBC),
> +KVM_EXT_CFG("zvfh", ext_zvfh, KVM_RISCV_ISA_EXT_ZVFH),
> +KVM_EXT_CFG("zvfhmin", ext_zvfhmin, KVM_RISCV_ISA_EXT_ZVFHMIN),
> +KVM_EXT_CFG("zvkb", ext_zvkb, KVM_RISCV_ISA_EXT_ZVKB),
> +KVM_EXT_CFG("zvkg", ext_zvkg, KVM_RISCV_ISA_EXT_ZVKG),
> +KVM_EXT_CFG("zvkned", ext_zvkned, KVM_RISCV_ISA_EXT_ZVKNED),
> +KVM_EXT_CFG("zvknha", ext_zvknha, KVM_RISCV_ISA_EXT_ZVKNHA),
> +KVM_EXT_CFG("zvknhb", ext_zvknhb, KVM_RISCV_ISA_EXT_ZVKNHB),
> +KVM_EXT_CFG("zvksed", ext_zvksed, KVM_RISCV_ISA_EXT_ZVKSED),
> +KVM_EXT_CFG("zvksh", ext_zvksh, KVM_RISCV_ISA_EXT_ZVKSH),
> +KVM_EXT_CFG("zvkt", ext_zvkt, KVM_RISCV_ISA_EXT_ZVKT),
> +KVM_EXT_CFG("smstateen", ext_smstateen, KVM_RISCV_ISA_EXT_SMSTATEEN),
>  KVM_EXT_CFG("ssaia", ext_ssaia, KVM_RISCV_ISA_EXT_SSAIA),
>  KVM_EXT_CFG("sstc", ext_sstc, KVM_RISCV_ISA_EXT_SSTC),
>  KVM_EXT_CFG("svinval", ext_svinval, KVM_RISCV_ISA_EXT_SVINVAL),
> --
> 2.43.2
>
>



Re: [RFC 1/2] hw/riscv: Add server platform reference machine

2024-03-05 Thread Wu, Fei
Hi Conor,

On 3/6/2024 8:27 AM, Conor Dooley wrote:
> On Mon, Mar 04, 2024 at 06:25:39PM +0800, Fei Wu wrote:
> 
>> +name = riscv_isa_string(cpu_ptr);
>> +qemu_fdt_setprop_string(ms->fdt, cpu_name, "riscv,isa", name);
>> +g_free(name);
> 
> Please use riscv_isa_write_fdt() here so that you populate more than the
> deprecated property here please.
> 
Sure, I saw it's been done in virt.c recently, I will catch up all the
improvements from virt.c to this board.

Thanks,
Fei.

> Thanks,
> Conor.




Re: [RFC PATCH v6 19/23] hw/intc/arm_gicv3: Implement NMI interrupt prioirty

2024-03-05 Thread Jinjie Ruan via



On 2024/3/6 6:36, Richard Henderson wrote:
> On 3/4/24 21:03, Jinjie Ruan via wrote:
>> -static bool irqbetter(GICv3CPUState *cs, int irq, uint8_t prio)
>> +static bool irqbetter(GICv3CPUState *cs, int irq, uint8_t prio,
>> +  bool has_superprio)
>>   {
>>   /* Return true if this IRQ at this priority should take
>>    * precedence over the current recorded highest priority
>> @@ -33,11 +34,22 @@ static bool irqbetter(GICv3CPUState *cs, int irq,
>> uint8_t prio)
>>   if (prio < cs->hppi.prio) {
>>   return true;
>>   }
>> +
>> +    /*
>> + * The same priority IRQ with superpriority should signal to the CPU
>> + * as it have the priority higher than the labelled 0x80 or 0x00.
>> + */
>> +    if (prio == cs->hppi.prio && !cs->hppi.superprio && has_superprio) {
>> +    return true;
>> +    }
>> +
>>   /* If multiple pending interrupts have the same priority then it
>> is an
>>    * IMPDEF choice which of them to signal to the CPU. We choose to
>> - * signal the one with the lowest interrupt number.
>> + * signal the one with the lowest interrupt number if they don't
>> have
>> + * superpriority.
>>    */
>> -    if (prio == cs->hppi.prio && irq <= cs->hppi.irq) {
>> +    if (prio == cs->hppi.prio && !cs->hppi.superprio &&
>> +    !has_superprio && irq <= cs->hppi.irq) {
>>   return true;
>>   }
>>   return false;
> 
> This should be reordered for clarity:
> 
>     if (prio != cs->hppi.prio) {
>     return prio < cs->hppi.prio;
>     }
> 
>     if (has_superprio != cs->hppi.superprio) {
>     return has_superprio;
>     }
> 
>     return irq <= cs->hppa.irq;
> 
> So that we do not have to keep incorporating previous tests.

This looks much cleaner.

> 
> 
> 
>> @@ -129,6 +141,43 @@ static uint32_t gicr_int_pending(GICv3CPUState *cs)
>>   return pend;
>>   }
>>   +static bool gicv3_get_priority(GICv3CPUState *cs, bool is_redist,
>> +   uint8_t *prio, int irq)
>> +{
>> +    bool has_superprio = false;
>> +    uint32_t superprio = 0x0;
>> +
>> +    if (is_redist) {
>> +    superprio = extract32(cs->gicr_isuperprio, irq, 1);
>> +    } else {
>> +    superprio = *gic_bmp_ptr32(cs->gic->superprio, irq);
>> +    superprio = superprio & (1 << (irq & 0x1f));
>> +    }
>> +
>> +    if (superprio) {
>> +    has_superprio = true;
>> +
>> +    /* DS = 0 & Non-secure NMI */
>> +    if (!(cs->gic->gicd_ctlr & GICD_CTLR_DS) &&
>> +    ((is_redist && extract32(cs->gicr_igroupr0, irq, 1)) ||
>> + (!is_redist && gicv3_gicd_group_test(cs->gic, irq {
>> +    *prio = 0x80;
>> +    } else {
>> +    *prio = 0x0;
>> +    }
>> +    } else {
>> +    has_superprio = false;
>> +
>> +    if (is_redist) {
>> +    *prio = cs->gicr_ipriorityr[irq];
>> +    } else {
>> +    *prio = cs->gic->gicd_ipriority[irq];
>> +    }
>> +    }
>> +
>> +    return has_superprio;
>> +}
> 
> has_superprio == superprio -- you can eliminate has_superprio,
> or even leverage the code path:
> 
>     if (superprio) {
>     ...
>     return true;
>     }
> 
>     if (is_redist)
>     ...
>     return false;
> 
>> @@ -168,9 +219,10 @@ static void
>> gicv3_redist_update_noirqset(GICv3CPUState *cs)
>>   if ((cs->gicr_ctlr & GICR_CTLR_ENABLE_LPIS) &&
>> cs->gic->lpi_enable &&
>>   (cs->gic->gicd_ctlr & GICD_CTLR_EN_GRP1NS) &&
>>   (cs->hpplpi.prio != 0xff)) {
>> -    if (irqbetter(cs, cs->hpplpi.irq, cs->hpplpi.prio)) {
>> +    if (irqbetter(cs, cs->hpplpi.irq, cs->hpplpi.prio, false)) {
> 
> New argument should be hpplpi.superprio.
> 
> There are several places where we're setting irq and prio which might
> need to clear superprio, e.g. update_for_one_lpi.  But also anywhere
> else that deals with PendingIrq.
> 
>> +    cs->hppi.superprio = 0x0;
> 
> false, not 0x0.
> 
> 
> r~



RE: [PATCH v4 4/8] migration/multifd: add qpl compression method

2024-03-05 Thread Liu, Yuan1
> -Original Message-
> From: Fabiano Rosas 
> Sent: Wednesday, March 6, 2024 4:58 AM
> To: Liu, Yuan1 ; pet...@redhat.com
> Cc: qemu-devel@nongnu.org; hao.xi...@bytedance.com;
> bryan.zh...@bytedance.com; Liu, Yuan1 ; Zou, Nanhai
> 
> Subject: Re: [PATCH v4 4/8] migration/multifd: add qpl compression method
> 
> Yuan Liu  writes:
> 
> > add the Query Processing Library (QPL) compression method
> >
> > Although both qpl and zlib support deflate compression, qpl will
> > only use the In-Memory Analytics Accelerator(IAA) for compression
> > and decompression, and IAA is not compatible with the Zlib in
> > migration, so qpl is used as a new compression method for migration.
> >
> > How to enable qpl compression during migration:
> > migrate_set_parameter multifd-compression qpl
> >
> > The qpl only supports one compression level, there is no qpl
> > compression level parameter added, users do not need to specify
> > the qpl compression level.
> >
> > Signed-off-by: Yuan Liu 
> > Reviewed-by: Nanhai Zou 
> > ---
> >  hw/core/qdev-properties-system.c |   2 +-
> >  migration/meson.build|   1 +
> >  migration/multifd-qpl.c  | 158 +++
> >  migration/multifd.h  |   1 +
> >  qapi/migration.json  |   7 +-
> >  5 files changed, 167 insertions(+), 2 deletions(-)
> >  create mode 100644 migration/multifd-qpl.c
> >
> > diff --git a/hw/core/qdev-properties-system.c b/hw/core/qdev-properties-
> system.c
> > index 1a396521d5..b4f0e5cbdb 100644
> > --- a/hw/core/qdev-properties-system.c
> > +++ b/hw/core/qdev-properties-system.c
> > @@ -658,7 +658,7 @@ const PropertyInfo qdev_prop_fdc_drive_type = {
> >  const PropertyInfo qdev_prop_multifd_compression = {
> >  .name = "MultiFDCompression",
> >  .description = "multifd_compression values, "
> > -   "none/zlib/zstd",
> > +   "none/zlib/zstd/qpl",
> >  .enum_table = _lookup,
> >  .get = qdev_propinfo_get_enum,
> >  .set = qdev_propinfo_set_enum,
> > diff --git a/migration/meson.build b/migration/meson.build
> > index 92b1cc4297..c155c2d781 100644
> > --- a/migration/meson.build
> > +++ b/migration/meson.build
> > @@ -40,6 +40,7 @@ if get_option('live_block_migration').allowed()
> >system_ss.add(files('block.c'))
> >  endif
> >  system_ss.add(when: zstd, if_true: files('multifd-zstd.c'))
> > +system_ss.add(when: qpl, if_true: files('multifd-qpl.c'))
> >
> >  specific_ss.add(when: 'CONFIG_SYSTEM_ONLY',
> >  if_true: files('ram.c',
> > diff --git a/migration/multifd-qpl.c b/migration/multifd-qpl.c
> > new file mode 100644
> > index 00..6b94e732ac
> > --- /dev/null
> > +++ b/migration/multifd-qpl.c
> > @@ -0,0 +1,158 @@
> > +/*
> > + * Multifd qpl compression accelerator implementation
> > + *
> > + * Copyright (c) 2023 Intel Corporation
> > + *
> > + * Authors:
> > + *  Yuan Liu
> > + *
> > + * 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/rcu.h"
> > +#include "exec/ramblock.h"
> > +#include "exec/target_page.h"
> > +#include "qapi/error.h"
> > +#include "migration.h"
> > +#include "trace.h"
> > +#include "options.h"
> > +#include "multifd.h"
> > +#include "qpl/qpl.h"
> 
> I don't mind adding a skeleton upfront before adding the implementation,
> but adding the headers here hurts the review process. Reviewers will
> have to go digging through the next patches to be able to validate each
> of these. It's better to include them along with their usage.
> 
> What I would do in this patch is maybe just add the new option, the
> .json and meson changes and this file with just:
> 
> static void multifd_qpl_register(void)
> {
> /* noop */
> }
> 
> Then in the next commit you can implement all the methods in one
> go. That way, the docstrings come along with the implementation, which
> also facilitates review.

Thanks for the guidance, I will implement it in the next version.

> > +
> > +struct qpl_data {
> 
> typedef struct {} QplData/QPLData, following QEMU's coding style.

I will fix it in next version

> > +qpl_job **job_array;
> > +/* the number of allocated jobs */
> > +uint32_t job_num;
> > +/* the size of data processed by a qpl job */
> > +uint32_t data_size;
> > +/* compressed data buffer */
> > +uint8_t *zbuf;
> > +/* the length of compressed data */
> > +uint32_t *zbuf_hdr;
> > +};
> > +
> > +/**
> > + * qpl_send_setup: setup send side
> > + *
> > + * Setup each channel with QPL compression.
> > + *
> > + * Returns 0 for success or -1 for error
> > + *
> > + * @p: Params for the channel that we are using
> > + * @errp: pointer to an error
> > + */
> > +static int qpl_send_setup(MultiFDSendParams *p, Error **errp)
> > +{
> > +/* Implement in next patch */
> > +return -1;
> > +}
> > +
> > +/**
> > + * qpl_send_cleanup: cleanup 

Re: [External] Re: [PATCH v1 1/1] memory tier: acpi/hmat: create CPUless memory tiers after obtaining HMAT info

2024-03-05 Thread Huang, Ying
"Ho-Ren (Jack) Chuang"  writes:

> On Sun, Mar 3, 2024 at 6:42 PM Huang, Ying  wrote:
>>
>> Hi, Jack,
>>
>> "Ho-Ren (Jack) Chuang"  writes:
>>
>> > * Introduce `mt_init_with_hmat()`
>> > We defer memory tier initialization for those CPUless NUMA nodes
>> > until acquiring HMAT info. `mt_init_with_hmat()` is introduced to
>> > post-create CPUless memory tiers after obtaining HMAT info.
>> > It iterates through each CPUless memory node, creating memory tiers if
>> > necessary. Finally, it calculates demotion tables again at the end.
>> >
>> > * Introduce `hmat_find_alloc_memory_type()`
>> > Find or allocate a memory type in the `hmat_memory_types` list.
>> >
>> > * Make `set_node_memory_tier()` more generic
>> > This function can also be used for setting other memory types for a node.
>> > To do so, a new argument is added to specify a memory type.
>> >
>> > * Handle cases where there is no HMAT when creating memory tiers
>> > If no HMAT is specified, it falls back to using `default_dram_type`.
>> >
>> > * Change adist calculation code to use another new lock, mt_perf_lock.
>> > Iterating through CPUlist nodes requires holding the `memory_tier_lock`.
>> > However, `mt_calc_adistance()` will end up trying to acquire the same lock,
>> > leading to a potential deadlock. Therefore, we propose introducing a
>> > standalone `mt_perf_lock` to protect `default_dram_perf`. This approach not
>> > only avoids deadlock but also prevents holding a large lock simultaneously.
>>
>> The patch description is used to described why we need the change, and
>> how we do that, but not what we do.  People can tell what is done from
>> the code itself.
>>
>
> Got it. Thanks. Will rewrite it after the code is finalized.
>
>> > Signed-off-by: Ho-Ren (Jack) Chuang 
>> > Signed-off-by: Hao Xiang 
>> > ---
>> >  drivers/acpi/numa/hmat.c |  3 ++
>> >  include/linux/memory-tiers.h |  6 +++
>> >  mm/memory-tiers.c| 76 
>> >  3 files changed, 77 insertions(+), 8 deletions(-)
>> >
>> > diff --git a/drivers/acpi/numa/hmat.c b/drivers/acpi/numa/hmat.c
>> > index d6b85f0f6082..9f57338b3cb5 100644
>> > --- a/drivers/acpi/numa/hmat.c
>> > +++ b/drivers/acpi/numa/hmat.c
>> > @@ -1038,6 +1038,9 @@ static __init int hmat_init(void)
>> >   if (!hmat_set_default_dram_perf())
>> >   register_mt_adistance_algorithm(_adist_nb);
>> >
>> > + /* Post-create CPUless memory tiers after getting HMAT info */
>> > + mt_init_with_hmat();
>> > +
>> >   return 0;
>> >  out_put:
>> >   hmat_free_structures();
>> > diff --git a/include/linux/memory-tiers.h b/include/linux/memory-tiers.h
>> > index 69e781900082..2f845e90c033 100644
>> > --- a/include/linux/memory-tiers.h
>> > +++ b/include/linux/memory-tiers.h
>> > @@ -48,6 +48,7 @@ int mt_calc_adistance(int node, int *adist);
>> >  int mt_set_default_dram_perf(int nid, struct access_coordinate *perf,
>> >const char *source);
>> >  int mt_perf_to_adistance(struct access_coordinate *perf, int *adist);
>> > +void mt_init_with_hmat(void);
>>
>> HMAT isn't universally available.  It's a driver in fact.  So, don't put
>> driver specific code in general code.
>>
>
> Please see below regarding "move code to hmat.c"
>
>> >  #ifdef CONFIG_MIGRATION
>> >  int next_demotion_node(int node);
>> >  void node_get_allowed_targets(pg_data_t *pgdat, nodemask_t *targets);
>> > @@ -136,5 +137,10 @@ static inline int mt_perf_to_adistance(struct 
>> > access_coordinate *perf, int *adis
>> >  {
>> >   return -EIO;
>> >  }
>> > +
>> > +static inline void mt_init_with_hmat(void)
>> > +{
>> > +
>> > +}
>> >  #endif   /* CONFIG_NUMA */
>> >  #endif  /* _LINUX_MEMORY_TIERS_H */
>> > diff --git a/mm/memory-tiers.c b/mm/memory-tiers.c
>> > index 0537664620e5..7a0a579b3deb 100644
>> > --- a/mm/memory-tiers.c
>> > +++ b/mm/memory-tiers.c
>> > @@ -35,7 +35,9 @@ struct node_memory_type_map {
>> >  };
>> >
>> >  static DEFINE_MUTEX(memory_tier_lock);
>> > +static DEFINE_MUTEX(mt_perf_lock);
>> >  static LIST_HEAD(memory_tiers);
>> > +static LIST_HEAD(hmat_memory_types);
>> >  static struct node_memory_type_map node_memory_types[MAX_NUMNODES];
>> >  struct memory_dev_type *default_dram_type;
>> >
>> > @@ -502,7 +504,7 @@ static inline void __init_node_memory_type(int node, 
>> > struct memory_dev_type *mem
>> >   }
>> >  }
>> >
>> > -static struct memory_tier *set_node_memory_tier(int node)
>> > +static struct memory_tier *set_node_memory_tier(int node, struct 
>> > memory_dev_type *new_memtype)
>>
>> No. memory_dev_type are passed to the function via 
>> node_memory_types[node].memtype.
>>
>
> Got it. Will mimic the way kmem.c does. Thanks.
>
>> >  {
>> >   struct memory_tier *memtier;
>> >   struct memory_dev_type *memtype;
>> > @@ -514,7 +516,7 @@ static struct memory_tier *set_node_memory_tier(int 
>> > node)
>> >   if (!node_state(node, N_MEMORY))
>> >   return ERR_PTR(-EINVAL);
>> >
>> > - 

Re: ARM hypervisors

2024-03-05 Thread Trilok Soni
On 3/5/2024 5:59 AM, Peter Maydell wrote:
> On Tue, 5 Mar 2024 at 13:40, RR NN  wrote:
>>
>> Hello
>> ARM hypervisors (pKVM, Gunyah) can run x86 OSs?
> 
> No. A hypervisor uses the host CPU's virtualization extensions
> to allow the guest code to run directly on the host CPU. This
> is why they're fast. This also means that they only work when
> the guest CPU is the same architecture as the host CPU.
> So you can run an x86 OS on an x86 host CPU, or an Arm
> OS on an Arm host CPU using a hypervisor, but you can't run
> a guest of the "wrong" architecture.

As explained above you can't run x86 Guest OS w/ above Hypervisors.

You can use the qemu/crosvm w/ above Hypervisors to do the ARM64
guest OS. You may be able to use Pixel device as well w/ the pKVM. 

I also suggest that you don't do the "reactions" with gmail. It 
doesn't help this conversation. 

Let us know what exactly you would like to experiment with above
Hypervisors. 

-- 
---Trilok Soni




RE: [PATCH v4 3/8] configure: add --enable-qpl build option

2024-03-05 Thread Liu, Yuan1
> -Original Message-
> From: Fabiano Rosas 
> Sent: Wednesday, March 6, 2024 4:32 AM
> To: Liu, Yuan1 ; pet...@redhat.com
> Cc: qemu-devel@nongnu.org; hao.xi...@bytedance.com;
> bryan.zh...@bytedance.com; Liu, Yuan1 ; Zou, Nanhai
> 
> Subject: Re: [PATCH v4 3/8] configure: add --enable-qpl build option
> 
> Yuan Liu  writes:
> 
> > add --enable-qpl and --disable-qpl options to enable and disable
> > the QPL compression method for multifd migration.
> >
> > the Query Processing Library (QPL) is an open-source library
> > that supports data compression and decompression features.
> >
> > The QPL compression is based on the deflate compression algorithm
> > and use Intel In-Memory Analytics Accelerator(IAA) hardware for
> > compression and decompression acceleration.
> >
> > Please refer to the following for more information about QPL
> >
> https://intel.github.io/qpl/documentation/introduction_docs/introduction.h
> tml
> >
> > Signed-off-by: Yuan Liu 
> > Reviewed-by: Nanhai Zou 
> > ---
> >  meson.build   | 18 ++
> >  meson_options.txt |  2 ++
> >  scripts/meson-buildoptions.sh |  3 +++
> >  3 files changed, 23 insertions(+)
> >
> > diff --git a/meson.build b/meson.build
> > index c1dc83e4c0..2dea1e6834 100644
> > --- a/meson.build
> > +++ b/meson.build
> > @@ -1197,6 +1197,22 @@ if not get_option('zstd').auto() or have_block
> >  required: get_option('zstd'),
> >  method: 'pkg-config')
> >  endif
> > +qpl = not_found
> > +if not get_option('qpl').auto()
> > +  libqpl = cc.find_library('qpl', required: false)
> > +  if not libqpl.found()
> > +error('libqpl not found, please install it from ' +
> > +
> 'https://intel.github.io/qpl/documentation/get_started_docs/installation.h
> tml')
> > +  endif
> > +  libaccel = cc.find_library('accel-config', required: false)
> > +  if not libaccel.found()
> > +error('libaccel-config not found, please install it from ' +
> > +'https://github.com/intel/idxd-config')
> 
> accel-config seems to be packaged by many distros, I'm not sure we need
> to reference the repository here.
> 
> https://repology.org/project/accel-config/versions

Yes, accel-config has been added to many distributions, I will use pkgconfig to 
detect the libaccel and the version(at least v4.0). 

I have a question, I didn't find accel-config installation package from 
https://repology.org/project/accel-config/versions. Does using this link also 
require the user to build an accel-config package, and then install it?

It is easy to install accel-config using the installation package, but I didn't 
find a repo that provides accel-config installation packages for most 
distributions.

First check accel-config is available through pktconfig, and if it is not 
available,
prompts users to install it from https://github.com/intel/idxd-config, is it OK?

> > +  endif
> > +  qpl = declare_dependency(dependencies: [libqpl, libaccel,
> > +cc.find_library('dl', required: get_option('qpl'))],
> > +link_args: ['-lstdc++'])
> > +endif
> >  virgl = not_found
> >
> >  have_vhost_user_gpu = have_tools and host_os == 'linux' and
> pixman.found()
> > @@ -2298,6 +2314,7 @@ config_host_data.set('CONFIG_MALLOC_TRIM',
> has_malloc_trim)
> >  config_host_data.set('CONFIG_STATX', has_statx)
> >  config_host_data.set('CONFIG_STATX_MNT_ID', has_statx_mnt_id)
> >  config_host_data.set('CONFIG_ZSTD', zstd.found())
> > +config_host_data.set('CONFIG_QPL', qpl.found())
> >  config_host_data.set('CONFIG_FUSE', fuse.found())
> >  config_host_data.set('CONFIG_FUSE_LSEEK', fuse_lseek.found())
> >  config_host_data.set('CONFIG_SPICE_PROTOCOL', spice_protocol.found())
> > @@ -4438,6 +4455,7 @@ summary_info += {'snappy support':snappy}
> >  summary_info += {'bzip2 support': libbzip2}
> >  summary_info += {'lzfse support': liblzfse}
> >  summary_info += {'zstd support':  zstd}
> > +summary_info += {'Query Processing Library support': qpl}
> >  summary_info += {'NUMA host support': numa}
> >  summary_info += {'capstone':  capstone}
> >  summary_info += {'libpmem support':   libpmem}
> > diff --git a/meson_options.txt b/meson_options.txt
> > index 0a99a059ec..06cd675572 100644
> > --- a/meson_options.txt
> > +++ b/meson_options.txt
> > @@ -259,6 +259,8 @@ option('xkbcommon', type : 'feature', value :
> 'auto',
> > description: 'xkbcommon support')
> >  option('zstd', type : 'feature', value : 'auto',
> > description: 'zstd compression support')
> > +option('qpl', type : 'feature', value : 'auto',
> > +   description: 'Query Processing Library support')
> >  option('fuse', type: 'feature', value: 'auto',
> > description: 'FUSE block device export')
> >  option('fuse_lseek', type : 'feature', value : 'auto',
> > diff --git a/scripts/meson-buildoptions.sh b/scripts/meson-
> buildoptions.sh
> > index 680fa3f581..784f74fde9 100644
> > --- a/scripts/meson-buildoptions.sh
> > +++ 

Re: [PATCH 1/2] linux-headers: Update to Linux v6.8-rc6

2024-03-05 Thread Alistair Francis
On Mon, Mar 4, 2024 at 11:48 PM Daniel Henrique Barboza
 wrote:
>
> The idea with this update is to get the latest KVM caps for RISC-V.
>
> Signed-off-by: Daniel Henrique Barboza 

Acked-by: Alistair Francis 

Alistair

> ---
>  include/standard-headers/drm/drm_fourcc.h |  10 +-
>  include/standard-headers/linux/ethtool.h  |  41 +++--
>  .../standard-headers/linux/virtio_config.h|   8 +-
>  include/standard-headers/linux/virtio_pci.h   |  68 +
>  include/standard-headers/linux/virtio_pmem.h  |   7 +
>  linux-headers/asm-generic/unistd.h|  15 +-
>  linux-headers/asm-mips/mman.h |   2 +-
>  linux-headers/asm-mips/unistd_n32.h   |   5 +
>  linux-headers/asm-mips/unistd_n64.h   |   5 +
>  linux-headers/asm-mips/unistd_o32.h   |   5 +
>  linux-headers/asm-powerpc/unistd_32.h |   5 +
>  linux-headers/asm-powerpc/unistd_64.h |   5 +
>  linux-headers/asm-riscv/kvm.h |  40 +
>  linux-headers/asm-s390/unistd_32.h|   5 +
>  linux-headers/asm-s390/unistd_64.h|   5 +
>  linux-headers/asm-x86/kvm.h   |   3 +
>  linux-headers/asm-x86/unistd_32.h |   5 +
>  linux-headers/asm-x86/unistd_64.h |   5 +
>  linux-headers/asm-x86/unistd_x32.h|   5 +
>  linux-headers/linux/iommufd.h |  79 ++
>  linux-headers/linux/kvm.h | 140 +++---
>  linux-headers/linux/userfaultfd.h |  29 +++-
>  linux-headers/linux/vfio.h|   1 +
>  23 files changed, 381 insertions(+), 112 deletions(-)
>
> diff --git a/include/standard-headers/drm/drm_fourcc.h 
> b/include/standard-headers/drm/drm_fourcc.h
> index 3afb70160f..b72917073d 100644
> --- a/include/standard-headers/drm/drm_fourcc.h
> +++ b/include/standard-headers/drm/drm_fourcc.h
> @@ -53,7 +53,7 @@ extern "C" {
>   * Format modifiers may change any property of the buffer, including the 
> number
>   * of planes and/or the required allocation size. Format modifiers are
>   * vendor-namespaced, and as such the relationship between a fourcc code and 
> a
> - * modifier is specific to the modifer being used. For example, some 
> modifiers
> + * modifier is specific to the modifier being used. For example, some 
> modifiers
>   * may preserve meaning - such as number of planes - from the fourcc code,
>   * whereas others may not.
>   *
> @@ -78,7 +78,7 @@ extern "C" {
>   *   format.
>   * - Higher-level programs interfacing with KMS/GBM/EGL/Vulkan/etc: these 
> users
>   *   see modifiers as opaque tokens they can check for equality and 
> intersect.
> - *   These users musn't need to know to reason about the modifier value
> + *   These users mustn't need to know to reason about the modifier value
>   *   (i.e. they are not expected to extract information out of the modifier).
>   *
>   * Vendors should document their modifier usage in as much detail as
> @@ -539,7 +539,7 @@ extern "C" {
>   * This is a tiled layout using 4Kb tiles in row-major layout.
>   * Within the tile pixels are laid out in 16 256 byte units / sub-tiles which
>   * are arranged in four groups (two wide, two high) with column-major layout.
> - * Each group therefore consits out of four 256 byte units, which are also 
> laid
> + * Each group therefore consists out of four 256 byte units, which are also 
> laid
>   * out as 2x2 column-major.
>   * 256 byte units are made out of four 64 byte blocks of pixels, producing
>   * either a square block or a 2:1 unit.
> @@ -1102,7 +1102,7 @@ drm_fourcc_canonicalize_nvidia_format_mod(uint64_t 
> modifier)
>   */
>
>  /*
> - * The top 4 bits (out of the 56 bits alloted for specifying vendor specific
> + * The top 4 bits (out of the 56 bits allotted for specifying vendor specific
>   * modifiers) denote the category for modifiers. Currently we have three
>   * categories of modifiers ie AFBC, MISC and AFRC. We can have a maximum of
>   * sixteen different categories.
> @@ -1418,7 +1418,7 @@ drm_fourcc_canonicalize_nvidia_format_mod(uint64_t 
> modifier)
>   * Amlogic FBC Memory Saving mode
>   *
>   * Indicates the storage is packed when pixel size is multiple of word
> - * boudaries, i.e. 8bit should be stored in this mode to save allocation
> + * boundaries, i.e. 8bit should be stored in this mode to save allocation
>   * memory.
>   *
>   * This mode reduces body layout to 3072 bytes per 64x32 superblock with
> diff --git a/include/standard-headers/linux/ethtool.h 
> b/include/standard-headers/linux/ethtool.h
> index 99fcddf04f..dfb54eff6f 100644
> --- a/include/standard-headers/linux/ethtool.h
> +++ b/include/standard-headers/linux/ethtool.h
> @@ -1266,6 +1266,8 @@ struct ethtool_rxfh_indir {
>   * hardware hash key.
>   * @hfunc: Defines the current RSS hash function used by HW (or to be set 
> to).
>   * Valid values are one of the %ETH_RSS_HASH_*.
> + * @input_xfrm: Defines how the input data is transformed. 

Re: Qemu sdhci-pci device can't be recognized by Linux kernel

2024-03-05 Thread Alistair Francis
On Wed, Feb 28, 2024 at 12:19 AM Li, Yong  wrote:
>
> Hello,
>
> QEMU virt platform of RISCV-64 can emulate the mmc device by using below 
> parameters:
> -device sdhci-pci,sd-spec-version=3 \
> -drive if=none,file=disk.img,format=raw,id=MMC1 \
> -device sd-card,drive=MMC1
>
> And as to u-boot, it do can recognize the mmc device and load the linux 
> kernel from the sdcard partition.
> But the mmc device can't be recognized by the linux kernel so that the root 
> filesystem in the sdcard can't be loaded.
>
> The logs are as below, any thoughts ? Thanks
>
>
> Starting kernel ...
>
> [0.00] Linux version 6.7.0-rc3-g2bb52284d571-dirty 
> (intel@intel-OptiPlex-7090) (riscv64-linux-gnu-gcc (Ubuntu 
> 9.4.0-1ubuntu1~20.04) 9.4.0, GNU ld (GNU Binutils for Ubuntu) 2.34) #11 SMP 
> Tue Feb 27 16:04:26 CST 2024
> [0.00] random: crng init done
> [0.00] Machine model: riscv-virtio,qemu
> [0.00] SBI specification v1.0 detected
> [0.00] SBI implementation ID=0x1 Version=0x10003
> [0.00] SBI TIME extension detected
> [0.00] SBI IPI extension detected
> [0.00] SBI RFENCE extension detected
> [0.00] earlycon: ns16550a0 at MMIO 0x1000 (options '')
> [0.00] printk: legacy bootconsole [ns16550a0] enabled
> [0.00] efi: UEFI not found.
> [0.00] OF: reserved mem: 0x8000..0x8003 (256 
> KiB) nomap non-reusable mmode_resv1@8000
> [0.00] OF: reserved mem: 0x8004..0x8005 (128 
> KiB) nomap non-reusable mmode_resv0@8004
> [0.00] Zone ranges:
> [0.00]   DMA32[mem 0x8000-0x]
> [0.00]   Normal   [mem 0x0001-0x00017fff]
> [0.00] Movable zone start for each node
> [0.00] Early memory node ranges
> [0.00]   node   0: [mem 0x8000-0x8005]
> [0.00]   node   0: [mem 0x8006-0x00017fff]
> [0.00] Initmem setup node 0 [mem 
> 0x8000-0x00017fff]
> [0.00] SBI HSM extension detected
> [0.00] CPU with hartid=1 is not available
> [0.00] Falling back to deprecated "riscv,isa"
> [0.00] riscv: base ISA extensions acdfhim
> [0.00] riscv: ELF capabilities acdfim
> [0.00] percpu: Embedded 20 pages/cpu s41976 r8192 d31752 u81920
> [0.00] Kernel command line: root=/dev/vda1 ro earlycon 
> console=ttyS0,115200n8
> [0.00] Dentry cache hash table entries: 524288 (order: 10, 4194304 
> bytes, linear)
> [0.00] Inode-cache hash table entries: 262144 (order: 9, 2097152 
> bytes, linear)
> [0.00] Built 1 zonelists, mobility grouping on.  Total pages: 1032192
> [0.00] mem auto-init: stack:off, heap alloc:off, heap free:off
> [0.00] software IO TLB: area num 1.
> [0.00] software IO TLB: mapped [mem 
> 0xfaec6000-0xfeec6000] (64MB)
> [0.00] Virtual kernel memory layout:
> [0.00]   fixmap : 0xff1bfea0 - 0xff1bff00   (6144 
> kB)
> [0.00]   pci io : 0xff1bff00 - 0xff1c   (  16 
> MB)
> [0.00]  vmemmap : 0xff1c - 0xff20   (1024 
> TB)
> [0.00]  vmalloc : 0xff20 - 0xff60   
> (16384 TB)
> [0.00]  modules : 0x01589000 - 0x8000   (2026 
> MB)
> [0.00]   lowmem : 0xff60 - 0xff61   (4096 
> MB)
> [0.00]   kernel : 0x8000 - 0x   (2047 
> MB)
> [0.00] Memory: 4016708K/4194304K available (9472K kernel code, 4986K 
> rwdata, 4096K rodata, K init, 502K bss, 177596K reserved, 0K cma-reserved)
> [0.00] SLUB: HWalign=64, Order=0-3, MinObjects=0, CPUs=1, Nodes=1
> [0.00] rcu: Hierarchical RCU implementation.
> [0.00] rcu: RCU restricting CPUs from NR_CPUS=64 to nr_cpu_ids=1.
> [0.00] rcu: RCU debug extended QS entry/exit.
> [0.00]  Tracing variant of Tasks RCU enabled.
> [0.00] rcu: RCU calculated value of scheduler-enlistment delay is 25 
> jiffies.
> [0.00] rcu: Adjusting geometry for rcu_fanout_leaf=16, nr_cpu_ids=1
> [0.00] NR_IRQS: 64, nr_irqs: 64, preallocated irqs: 0
> [0.00] riscv-intc: 64 local interrupts mapped using AIA
> [0.00] riscv-imsic: imsics@2800: invalid cpuid for parent irq1
> [0.00] riscv-imsic: imsics@2800: providing IPIs using interrupt 1
> [0.00] rcu: srcu_init: Setting srcu_struct sizes based on contention.
> [0.00] clocksource: riscv_clocksource: mask: 0x 
> max_cycles: 0x24e6a1710, max_idle_ns: 440795202120 ns
> [0.84] sched_clock: 64 bits at 10MHz, resolution 100ns, wraps every 
> 4398046511100ns
> [0.000338] riscv-timer: Timer interrupt in S-mode is available via sstc 
> extension
> [

Re: [PATCH v6 0/9] riscv: set vstart_eq_zero on mark_vs_dirty

2024-03-05 Thread Alistair Francis
On Thu, Feb 22, 2024 at 7:33 AM Daniel Henrique Barboza
 wrote:
>
> Hi,
>
> In this version 2 new patches were added:
>
> - patch 5 eliminates the 'cpu_vl' global, and do_vsetvl() now loads 'vl'
>   directly from env. This was suggested by Richard in the v5 review;
>
> - patch 9 does a change in how we're doing the loops in ldst helpers.
>   This was also proposed by Richard but back in v2.
>
> Patch 9 is not related to what we're fixing here but let's fold it in
> and avoid leaving any code suggestions behind.
>
> Series based on alistair/riscv-to-apply.next.
>
> Patches missing acks/reviews: 5 and 9
>
> Changes from v5:
> - patch 5 (new): remove 'cpu_vl' global
> - patch 9 (new): change the loop in ldst helpers
> - v5 link: 
> https://lore.kernel.org/qemu-riscv/20240221022252.252872-1-dbarb...@ventanamicro.com/
>
> Daniel Henrique Barboza (8):
>   trans_rvv.c.inc: mark_vs_dirty() before loads and stores
>   trans_rvv.c.inc: remove 'is_store' bool from load/store fns
>   target/riscv: remove 'over' brconds from vector trans
>   target/riscv/translate.c: remove 'cpu_vstart' global
>   target/riscv: remove 'cpu_vl' global
>   target/riscv/vector_helper.c: set vstart = 0 in GEN_VEXT_VSLIDEUP_VX()
>   trans_rvv.c.inc: remove redundant mark_vs_dirty() calls
>   target/riscv/vector_helper.c: optimize loops in ldst helpers
>
> Ivan Klokov (1):
>   target/riscv: Clear vstart_qe_zero flag

Looks good! Just conflicts with the Ztso extension support that was
recently added in the RISC-V tree

Alistair

>
>  target/riscv/insn_trans/trans_rvbf16.c.inc |  18 +-
>  target/riscv/insn_trans/trans_rvv.c.inc| 294 ++---
>  target/riscv/insn_trans/trans_rvvk.c.inc   |  30 +--
>  target/riscv/translate.c   |  11 +-
>  target/riscv/vector_helper.c   |   7 +-
>  5 files changed, 104 insertions(+), 256 deletions(-)
>
> --
> 2.43.2
>
>



Re: [PATCH] tests: riscv64: Use 'zfa' instead of 'Zfa'

2024-03-05 Thread Alistair Francis
On Fri, Mar 1, 2024 at 4:07 AM Christoph Müllner
 wrote:
>
> Running test-fcvtmod triggers the following deprecation warning:
>   warning: CPU property 'Zfa' is deprecated. Please use 'zfa' instead
> Let's fix that.
>
> Signed-off-by: Christoph Müllner 

Thanks!

Applied to riscv-to-apply.next

Alistair

> ---
>  tests/tcg/riscv64/Makefile.target | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/tests/tcg/riscv64/Makefile.target 
> b/tests/tcg/riscv64/Makefile.target
> index a7e390c384..4da5b9a3b3 100644
> --- a/tests/tcg/riscv64/Makefile.target
> +++ b/tests/tcg/riscv64/Makefile.target
> @@ -17,4 +17,4 @@ run-test-aes: QEMU_OPTS += -cpu rv64,zk=on
>  TESTS += test-fcvtmod
>  test-fcvtmod: CFLAGS += -march=rv64imafdc
>  test-fcvtmod: LDFLAGS += -static
> -run-test-fcvtmod: QEMU_OPTS += -cpu rv64,d=true,Zfa=true
> +run-test-fcvtmod: QEMU_OPTS += -cpu rv64,d=true,zfa=true
> --
> 2.43.2
>
>



Re: [PULL 0/4] machine development tool

2024-03-05 Thread Peter Xu
On Tue, Mar 05, 2024 at 03:43:41PM +0100, Markus Armbruster wrote:
> Peter Maydell  writes:
> 
> > On Mon, 4 Mar 2024 at 13:52, Maksim Davydov  
> > wrote:
> >>
> >> The following changes since commit 
> >> e1007b6bab5cf97705bf4f2aaec1f607787355b8:
> >>
> >>   Merge tag 'pull-request-2024-03-01' of https://gitlab.com/thuth/qemu 
> >> into staging (2024-03-01 10:14:32 +)
> >>
> >> are available in the Git repository at:
> >>
> >>   https://gitlab.com/davydov-max/qemu.git tags/pull-compare-mt-2024-03-04
> >>
> >> for you to fetch changes up to 7693a2e8518811a907d73a85807ee71dac8fabcb:
> >>
> >>   scripts: add script to compare compatibility properties (2024-03-04 
> >> 14:10:53 +0300)
> >>
> >> 
> >> Please note. This is the first pull request from me.
> >> My public GPG key is available here
> >> https://keys.openpgp.org/vks/v1/by-fingerprint/CDB5BEEF8837142579F5CDFE8E927E10F72F78D4
> >>
> >> 
> >> scripts: add a new script for machine development
> >>
> >> 
> >
> > Hi; I would prefer this to go through some existing submaintainer
> > tree if possible, please.
> 
> Migration?  QOM?  Not sure.  Cc'ing the maintainers anyway.

Yeah this seems like migration relevant.. however now I'm slightly confused
on when this script should be useful.

According to:

https://lore.kernel.org/qemu-devel/20240222153912.646053-5-davydov-...@yandex-team.ru/

This script runs QEMU to obtain compat_props of machines and
default values of different types of drivers to produce comparison
table. This table can be used to compare machine types to choose
the most suitable machine or compare binaries to be sure that
migration to the newer version will save all device
properties. Also the json or csv format of this table can be used
to check does a new machine affect the previous ones by comparing
tables with and without the new machine.

In regards to "choose the most suitable machine": why do you need to choose
a machine?

If it's pretty standalone setup, shouldn't we always try to use the latest
machine type if possible (as normally compat props are only used to keep
compatible with old machine types, and the default should always be
preferred). If it's a cluster setup, IMHO it should depend on the oldest
QEMU version that plans to be supported.  I don't see how such comparison
helps yet in either of the cases..

In regards to "compare binaries to be sure that migration to the newer
version will save all device properties": do we even support migrating
_between_ machine types??

Sololy relying on compat properties to detect device compatibility is also
not reliable.  For example, see VMStateField.field_exists() or similarly,
VMStateDescription.needed(), which are hooks that device can provide to
dynamically decide what device state to be saved/loaded.  Such things are
not reflected in compat properties, so even if compat properties of all
devices are the same between two machine types, it may not mean that the
migration stream will always be compatible.

Thanks,

-- 
Peter Xu




Re: [PATCH] tests: riscv64: Use 'zfa' instead of 'Zfa'

2024-03-05 Thread Alistair Francis
On Fri, Mar 1, 2024 at 4:07 AM Christoph Müllner
 wrote:
>
> Running test-fcvtmod triggers the following deprecation warning:
>   warning: CPU property 'Zfa' is deprecated. Please use 'zfa' instead
> Let's fix that.
>
> Signed-off-by: Christoph Müllner 

Reviewed-by: Alistair Francis 

Alistair

> ---
>  tests/tcg/riscv64/Makefile.target | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/tests/tcg/riscv64/Makefile.target 
> b/tests/tcg/riscv64/Makefile.target
> index a7e390c384..4da5b9a3b3 100644
> --- a/tests/tcg/riscv64/Makefile.target
> +++ b/tests/tcg/riscv64/Makefile.target
> @@ -17,4 +17,4 @@ run-test-aes: QEMU_OPTS += -cpu rv64,zk=on
>  TESTS += test-fcvtmod
>  test-fcvtmod: CFLAGS += -march=rv64imafdc
>  test-fcvtmod: LDFLAGS += -static
> -run-test-fcvtmod: QEMU_OPTS += -cpu rv64,d=true,Zfa=true
> +run-test-fcvtmod: QEMU_OPTS += -cpu rv64,d=true,zfa=true
> --
> 2.43.2
>
>



Re: [PATCH v6 9/9] target/riscv/vector_helper.c: optimize loops in ldst helpers

2024-03-05 Thread Alistair Francis
On Thu, Feb 22, 2024 at 7:33 AM Daniel Henrique Barboza
 wrote:
>
> Change the for loops in ldst helpers to do a single increment in the
> counter, and assign it env->vstart, to avoid re-reading from vstart
> every time.
>
> Suggested-by: Richard Henderson 
> Signed-off-by: Daniel Henrique Barboza 

Reviewed-by: Alistair Francis 

Alistair

> ---
>  target/riscv/vector_helper.c | 6 +++---
>  1 file changed, 3 insertions(+), 3 deletions(-)
>
> diff --git a/target/riscv/vector_helper.c b/target/riscv/vector_helper.c
> index cc7290a1bb..1ab386830a 100644
> --- a/target/riscv/vector_helper.c
> +++ b/target/riscv/vector_helper.c
> @@ -208,7 +208,7 @@ vext_ldst_stride(void *vd, void *v0, target_ulong base,
>  uint32_t esz = 1 << log2_esz;
>  uint32_t vma = vext_vma(desc);
>
> -for (i = env->vstart; i < env->vl; i++, env->vstart++) {
> +for (i = env->vstart; i < env->vl; env->vstart = ++i) {
>  k = 0;
>  while (k < nf) {
>  if (!vm && !vext_elem_mask(v0, i)) {
> @@ -274,7 +274,7 @@ vext_ldst_us(void *vd, target_ulong base, CPURISCVState 
> *env, uint32_t desc,
>  uint32_t esz = 1 << log2_esz;
>
>  /* load bytes from guest memory */
> -for (i = env->vstart; i < evl; i++, env->vstart++) {
> +for (i = env->vstart; i < evl; env->vstart = ++i) {
>  k = 0;
>  while (k < nf) {
>  target_ulong addr = base + ((i * nf + k) << log2_esz);
> @@ -388,7 +388,7 @@ vext_ldst_index(void *vd, void *v0, target_ulong base,
>  uint32_t vma = vext_vma(desc);
>
>  /* load bytes from guest memory */
> -for (i = env->vstart; i < env->vl; i++, env->vstart++) {
> +for (i = env->vstart; i < env->vl; env->vstart = ++i) {
>  k = 0;
>  while (k < nf) {
>  if (!vm && !vext_elem_mask(v0, i)) {
> --
> 2.43.2
>
>



Re: [PATCH v6 8/9] target/riscv: Clear vstart_qe_zero flag

2024-03-05 Thread Alistair Francis
On Thu, Feb 22, 2024 at 7:34 AM Daniel Henrique Barboza
 wrote:
>
> From: Ivan Klokov 
>
> The vstart_qe_zero flag is set at the beginning of the translation
> phase from the env->vstart variable. During the execution phase all
> functions will set env->vstart = 0 after a successful execution,
> but the vstart_eq_zero flag remains the same as at the start of the
> block. This will wrongly cause SIGILLs in translations that requires
> env->vstart = 0 and might be reading vstart_eq_zero = false.
>
> This patch adds a new finalize_rvv_inst() helper that is called at the
> end of each vector instruction that will both update vstart_eq_zero and
> do a mark_vs_dirty().
>
> Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1976
> Signed-off-by: Ivan Klokov 
> Signed-off-by: Daniel Henrique Barboza 
> Reviewed-by: Richard Henderson 

Reviewed-by: Alistair Francis 

Alistair

> ---
>  target/riscv/insn_trans/trans_rvbf16.c.inc |  6 +-
>  target/riscv/insn_trans/trans_rvv.c.inc| 78 --
>  target/riscv/insn_trans/trans_rvvk.c.inc   | 12 ++--
>  target/riscv/translate.c   |  6 ++
>  4 files changed, 56 insertions(+), 46 deletions(-)
>
> diff --git a/target/riscv/insn_trans/trans_rvbf16.c.inc 
> b/target/riscv/insn_trans/trans_rvbf16.c.inc
> index a842e76a6b..0a9cd1ec31 100644
> --- a/target/riscv/insn_trans/trans_rvbf16.c.inc
> +++ b/target/riscv/insn_trans/trans_rvbf16.c.inc
> @@ -83,7 +83,7 @@ static bool trans_vfncvtbf16_f_f_w(DisasContext *ctx, 
> arg_vfncvtbf16_f_f_w *a)
> ctx->cfg_ptr->vlenb,
> ctx->cfg_ptr->vlenb, data,
> gen_helper_vfncvtbf16_f_f_w);
> -mark_vs_dirty(ctx);
> +finalize_rvv_inst(ctx);
>  return true;
>  }
>  return false;
> @@ -108,7 +108,7 @@ static bool trans_vfwcvtbf16_f_f_v(DisasContext *ctx, 
> arg_vfwcvtbf16_f_f_v *a)
> ctx->cfg_ptr->vlenb,
> ctx->cfg_ptr->vlenb, data,
> gen_helper_vfwcvtbf16_f_f_v);
> -mark_vs_dirty(ctx);
> +finalize_rvv_inst(ctx);
>  return true;
>  }
>  return false;
> @@ -135,7 +135,7 @@ static bool trans_vfwmaccbf16_vv(DisasContext *ctx, 
> arg_vfwmaccbf16_vv *a)
> ctx->cfg_ptr->vlenb,
> ctx->cfg_ptr->vlenb, data,
> gen_helper_vfwmaccbf16_vv);
> -mark_vs_dirty(ctx);
> +finalize_rvv_inst(ctx);
>  return true;
>  }
>  return false;
> diff --git a/target/riscv/insn_trans/trans_rvv.c.inc 
> b/target/riscv/insn_trans/trans_rvv.c.inc
> index db08efa278..1933a6f5c2 100644
> --- a/target/riscv/insn_trans/trans_rvv.c.inc
> +++ b/target/riscv/insn_trans/trans_rvv.c.inc
> @@ -167,7 +167,7 @@ static bool do_vsetvl(DisasContext *s, int rd, int rs1, 
> TCGv s2)
>
>  gen_helper_vsetvl(dst, tcg_env, s1, s2);
>  gen_set_gpr(s, rd, dst);
> -mark_vs_dirty(s);
> +finalize_rvv_inst(s);
>
>  gen_update_pc(s, s->cur_insn_len);
>  lookup_and_goto_ptr(s);
> @@ -187,7 +187,7 @@ static bool do_vsetivli(DisasContext *s, int rd, TCGv s1, 
> TCGv s2)
>
>  gen_helper_vsetvl(dst, tcg_env, s1, s2);
>  gen_set_gpr(s, rd, dst);
> -mark_vs_dirty(s);
> +finalize_rvv_inst(s);
>  gen_update_pc(s, s->cur_insn_len);
>  lookup_and_goto_ptr(s);
>  s->base.is_jmp = DISAS_NORETURN;
> @@ -636,6 +636,7 @@ static bool ldst_us_trans(uint32_t vd, uint32_t rs1, 
> uint32_t data,
>
>  fn(dest, mask, base, tcg_env, desc);
>
> +finalize_rvv_inst(s);
>  return true;
>  }
>
> @@ -791,6 +792,7 @@ static bool ldst_stride_trans(uint32_t vd, uint32_t rs1, 
> uint32_t rs2,
>
>  fn(dest, mask, base, stride, tcg_env, desc);
>
> +finalize_rvv_inst(s);
>  return true;
>  }
>
> @@ -892,6 +894,7 @@ static bool ldst_index_trans(uint32_t vd, uint32_t rs1, 
> uint32_t vs2,
>
>  fn(dest, mask, base, index, tcg_env, desc);
>
> +finalize_rvv_inst(s);
>  return true;
>  }
>
> @@ -1022,7 +1025,7 @@ static bool ldff_trans(uint32_t vd, uint32_t rs1, 
> uint32_t data,
>
>  fn(dest, mask, base, tcg_env, desc);
>
> -mark_vs_dirty(s);
> +finalize_rvv_inst(s);
>  return true;
>  }
>
> @@ -1079,6 +1082,7 @@ static bool ldst_whole_trans(uint32_t vd, uint32_t rs1, 
> uint32_t nf,
>
>  fn(dest, base, tcg_env, desc);
>
> +finalize_rvv_inst(s);
>  return true;
>  }
>
> @@ -1168,7 +1172,7 @@ do_opivv_gvec(DisasContext *s, arg_rmrr *a, GVecGen3Fn 
> *gvec_fn,
> tcg_env, s->cfg_ptr->vlenb,
> s->cfg_ptr->vlenb, data, fn);
>  }
> -mark_vs_dirty(s);
> +finalize_rvv_inst(s);
>  return true;
>  }
>
> @@ -1219,7 +1223,7 @@ static bool opivx_trans(uint32_t vd, uint32_t rs1, 
> uint32_t vs2, uint32_t vm,
>
>  fn(dest, mask, src1, src2, tcg_env, desc);
>
> -mark_vs_dirty(s);
> +

Re: [PATCH v6 7/9] trans_rvv.c.inc: remove redundant mark_vs_dirty() calls

2024-03-05 Thread Alistair Francis
On Thu, Feb 22, 2024 at 7:33 AM Daniel Henrique Barboza
 wrote:
>
> trans_vmv_v_i , trans_vfmv_v_f and the trans_##NAME macro from
> GEN_VMV_WHOLE_TRANS() are calling mark_vs_dirty() in both branches of
> their 'ifs'. conditionals.
>
> Call it just once in the end like other functions are doing.
>
> Signed-off-by: Daniel Henrique Barboza 
> Reviewed-by: Richard Henderson 

Reviewed-by: Alistair Francis 

Alistair

> ---
>  target/riscv/insn_trans/trans_rvv.c.inc | 11 +++
>  1 file changed, 3 insertions(+), 8 deletions(-)
>
> diff --git a/target/riscv/insn_trans/trans_rvv.c.inc 
> b/target/riscv/insn_trans/trans_rvv.c.inc
> index 69f32d081e..db08efa278 100644
> --- a/target/riscv/insn_trans/trans_rvv.c.inc
> +++ b/target/riscv/insn_trans/trans_rvv.c.inc
> @@ -2044,7 +2044,6 @@ static bool trans_vmv_v_i(DisasContext *s, arg_vmv_v_i 
> *a)
>  if (s->vl_eq_vlmax && !(s->vta && s->lmul < 0)) {
>  tcg_gen_gvec_dup_imm(s->sew, vreg_ofs(s, a->rd),
>   MAXSZ(s), MAXSZ(s), simm);
> -mark_vs_dirty(s);
>  } else {
>  TCGv_i32 desc;
>  TCGv_i64 s1;
> @@ -2062,9 +2061,8 @@ static bool trans_vmv_v_i(DisasContext *s, arg_vmv_v_i 
> *a)
>s->cfg_ptr->vlenb, data));
>  tcg_gen_addi_ptr(dest, tcg_env, vreg_ofs(s, a->rd));
>  fns[s->sew](dest, s1, tcg_env, desc);
> -
> -mark_vs_dirty(s);
>  }
> +mark_vs_dirty(s);
>  return true;
>  }
>  return false;
> @@ -2591,7 +2589,6 @@ static bool trans_vfmv_v_f(DisasContext *s, 
> arg_vfmv_v_f *a)
>
>  tcg_gen_gvec_dup_i64(s->sew, vreg_ofs(s, a->rd),
>   MAXSZ(s), MAXSZ(s), t1);
> -mark_vs_dirty(s);
>  } else {
>  TCGv_ptr dest;
>  TCGv_i32 desc;
> @@ -2614,9 +2611,8 @@ static bool trans_vfmv_v_f(DisasContext *s, 
> arg_vfmv_v_f *a)
>  tcg_gen_addi_ptr(dest, tcg_env, vreg_ofs(s, a->rd));
>
>  fns[s->sew - 1](dest, t1, tcg_env, desc);
> -
> -mark_vs_dirty(s);
>  }
> +mark_vs_dirty(s);
>  return true;
>  }
>  return false;
> @@ -3524,12 +3520,11 @@ static bool trans_##NAME(DisasContext *s, arg_##NAME 
> * a)   \
>  if (s->vstart_eq_zero) {\
>  tcg_gen_gvec_mov(s->sew, vreg_ofs(s, a->rd),\
>   vreg_ofs(s, a->rs2), maxsz, maxsz);\
> -mark_vs_dirty(s);   \
>  } else {\
>  tcg_gen_gvec_2_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, a->rs2), \
> tcg_env, maxsz, maxsz, 0, gen_helper_vmvr_v); 
> \
> -mark_vs_dirty(s);   \
>  }   \
> +mark_vs_dirty(s);   \
>  return true;\
>  }   \
>  return false;   \
> --
> 2.43.2
>
>



Re: [PATCH v6 6/9] target/riscv/vector_helper.c: set vstart = 0 in GEN_VEXT_VSLIDEUP_VX()

2024-03-05 Thread Alistair Francis
On Thu, Feb 22, 2024 at 7:34 AM Daniel Henrique Barboza
 wrote:
>
> The helper isn't setting env->vstart = 0 after its execution, as it is
> expected from every vector instruction that completes successfully.
>
> Signed-off-by: Daniel Henrique Barboza 
> Reviewed-by: Richard Henderson 

Reviewed-by: Alistair Francis 

Alistair

> ---
>  target/riscv/vector_helper.c | 1 +
>  1 file changed, 1 insertion(+)
>
> diff --git a/target/riscv/vector_helper.c b/target/riscv/vector_helper.c
> index 84cec73eb2..cc7290a1bb 100644
> --- a/target/riscv/vector_helper.c
> +++ b/target/riscv/vector_helper.c
> @@ -4782,6 +4782,7 @@ void HELPER(NAME)(void *vd, void *v0, target_ulong s1, 
> void *vs2, \
>  } \
>  *((ETYPE *)vd + H(i)) = *((ETYPE *)vs2 + H(i - offset));  \
>  } \
> +env->vstart = 0;  \
>  /* set tail elements to 1s */ \
>  vext_set_elems_1s(vd, vta, vl * esz, total_elems * esz);  \
>  }
> --
> 2.43.2
>
>



Re: [PATCH v6 5/9] target/riscv: remove 'cpu_vl' global

2024-03-05 Thread Alistair Francis
On Thu, Feb 22, 2024 at 7:34 AM Daniel Henrique Barboza
 wrote:
>
> At this moment the global is used only in do_vsetvl(). Do a direct env
> load in do_vsetvl() to read 'vl' and remove the global.
>
> Suggested-by: Richard Henderson 
> Signed-off-by: Daniel Henrique Barboza 

Reviewed-by: Alistair Francis 

Alistair

> ---
>  target/riscv/insn_trans/trans_rvv.c.inc | 2 +-
>  target/riscv/translate.c| 3 +--
>  2 files changed, 2 insertions(+), 3 deletions(-)
>
> diff --git a/target/riscv/insn_trans/trans_rvv.c.inc 
> b/target/riscv/insn_trans/trans_rvv.c.inc
> index 58299d9bb8..69f32d081e 100644
> --- a/target/riscv/insn_trans/trans_rvv.c.inc
> +++ b/target/riscv/insn_trans/trans_rvv.c.inc
> @@ -157,7 +157,7 @@ static bool do_vsetvl(DisasContext *s, int rd, int rs1, 
> TCGv s2)
>
>  if (rd == 0 && rs1 == 0) {
>  s1 = tcg_temp_new();
> -tcg_gen_mov_tl(s1, cpu_vl);
> +tcg_gen_ld_tl(s1, tcg_env, offsetof(CPURISCVState, vl));
>  } else if (rs1 == 0) {
>  /* As the mask is at least one bit, RV_VLEN_MAX is >= VLMAX */
>  s1 = tcg_constant_tl(RV_VLEN_MAX);
> diff --git a/target/riscv/translate.c b/target/riscv/translate.c
> index f2f0593830..3040f5e0e4 100644
> --- a/target/riscv/translate.c
> +++ b/target/riscv/translate.c
> @@ -38,7 +38,7 @@
>  #undef  HELPER_H
>
>  /* global register indices */
> -static TCGv cpu_gpr[32], cpu_gprh[32], cpu_pc, cpu_vl;
> +static TCGv cpu_gpr[32], cpu_gprh[32], cpu_pc;
>  static TCGv_i64 cpu_fpr[32]; /* assume F and D extensions */
>  static TCGv load_res;
>  static TCGv load_val;
> @@ -1320,7 +1320,6 @@ void riscv_translate_init(void)
>  }
>
>  cpu_pc = tcg_global_mem_new(tcg_env, offsetof(CPURISCVState, pc), "pc");
> -cpu_vl = tcg_global_mem_new(tcg_env, offsetof(CPURISCVState, vl), "vl");
>  load_res = tcg_global_mem_new(tcg_env, offsetof(CPURISCVState, load_res),
>   "load_res");
>  load_val = tcg_global_mem_new(tcg_env, offsetof(CPURISCVState, load_val),
> --
> 2.43.2
>
>



Re: [PATCH v6 4/9] target/riscv/translate.c: remove 'cpu_vstart' global

2024-03-05 Thread Alistair Francis
On Thu, Feb 22, 2024 at 7:33 AM Daniel Henrique Barboza
 wrote:
>
> The global is unused after recent changes.
>
> Signed-off-by: Daniel Henrique Barboza 
> Reviewed-by: Richard Henderson 

Reviewed-by: Alistair Francis 

Alistair

> ---
>  target/riscv/translate.c | 4 +---
>  1 file changed, 1 insertion(+), 3 deletions(-)
>
> diff --git a/target/riscv/translate.c b/target/riscv/translate.c
> index 177418b2b9..f2f0593830 100644
> --- a/target/riscv/translate.c
> +++ b/target/riscv/translate.c
> @@ -38,7 +38,7 @@
>  #undef  HELPER_H
>
>  /* global register indices */
> -static TCGv cpu_gpr[32], cpu_gprh[32], cpu_pc, cpu_vl, cpu_vstart;
> +static TCGv cpu_gpr[32], cpu_gprh[32], cpu_pc, cpu_vl;
>  static TCGv_i64 cpu_fpr[32]; /* assume F and D extensions */
>  static TCGv load_res;
>  static TCGv load_val;
> @@ -1321,8 +1321,6 @@ void riscv_translate_init(void)
>
>  cpu_pc = tcg_global_mem_new(tcg_env, offsetof(CPURISCVState, pc), "pc");
>  cpu_vl = tcg_global_mem_new(tcg_env, offsetof(CPURISCVState, vl), "vl");
> -cpu_vstart = tcg_global_mem_new(tcg_env, offsetof(CPURISCVState, vstart),
> -"vstart");
>  load_res = tcg_global_mem_new(tcg_env, offsetof(CPURISCVState, load_res),
>   "load_res");
>  load_val = tcg_global_mem_new(tcg_env, offsetof(CPURISCVState, load_val),
> --
> 2.43.2
>
>



Re: [PATCH v6 3/9] target/riscv: remove 'over' brconds from vector trans

2024-03-05 Thread Alistair Francis
On Thu, Feb 22, 2024 at 7:32 AM Daniel Henrique Barboza
 wrote:
>
> Most of the vector translations has this following pattern at the start:
>
> TCGLabel *over = gen_new_label();
> tcg_gen_brcond_tl(TCG_COND_GEU, cpu_vstart, cpu_vl, over);
>
> And then right at the end:
>
>  gen_set_label(over);
>  return true;
>
> This means that if vstart >= vl we'll not set vstart = 0 at the end of
> the insns - this is done inside the helper that is being skipped.  The
> reason why this pattern hasn't been a bigger problem is because the
> conditional vstart >= vl is very rare.
>
> Checking all the helpers in vector_helper.c we see all of them with a
> pattern like this:
>
> for (i = env->vstart; i < vl; i++) {
> (...)
> }
> env->vstart = 0;
>
> Thus they can handle vstart >= vl case gracefully, with the benefit of
> setting env->vstart = 0 during the process.
>
> Remove all 'over' conditionals and let the helper set env->vstart = 0
> every time.
>
> While we're at it, remove the (vl == 0) brconds from trans_rvbf16.c.inc
> too since they're unneeded.
>
> Suggested-by: Richard Henderson 
> Signed-off-by: Daniel Henrique Barboza 
> Reviewed-by: Richard Henderson 

Reviewed-by: Alistair Francis 

Alistair

> ---
>  target/riscv/insn_trans/trans_rvbf16.c.inc |  12 ---
>  target/riscv/insn_trans/trans_rvv.c.inc| 117 -
>  target/riscv/insn_trans/trans_rvvk.c.inc   |  18 
>  3 files changed, 147 deletions(-)
>
> diff --git a/target/riscv/insn_trans/trans_rvbf16.c.inc 
> b/target/riscv/insn_trans/trans_rvbf16.c.inc
> index 8ee99df3f3..a842e76a6b 100644
> --- a/target/riscv/insn_trans/trans_rvbf16.c.inc
> +++ b/target/riscv/insn_trans/trans_rvbf16.c.inc
> @@ -71,11 +71,8 @@ static bool trans_vfncvtbf16_f_f_w(DisasContext *ctx, 
> arg_vfncvtbf16_f_f_w *a)
>
>  if (opfv_narrow_check(ctx, a) && (ctx->sew == MO_16)) {
>  uint32_t data = 0;
> -TCGLabel *over = gen_new_label();
>
>  gen_set_rm_chkfrm(ctx, RISCV_FRM_DYN);
> -tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over);
> -tcg_gen_brcond_tl(TCG_COND_GEU, cpu_vstart, cpu_vl, over);
>
>  data = FIELD_DP32(data, VDATA, VM, a->vm);
>  data = FIELD_DP32(data, VDATA, LMUL, ctx->lmul);
> @@ -87,7 +84,6 @@ static bool trans_vfncvtbf16_f_f_w(DisasContext *ctx, 
> arg_vfncvtbf16_f_f_w *a)
> ctx->cfg_ptr->vlenb, data,
> gen_helper_vfncvtbf16_f_f_w);
>  mark_vs_dirty(ctx);
> -gen_set_label(over);
>  return true;
>  }
>  return false;
> @@ -100,11 +96,8 @@ static bool trans_vfwcvtbf16_f_f_v(DisasContext *ctx, 
> arg_vfwcvtbf16_f_f_v *a)
>
>  if (opfv_widen_check(ctx, a) && (ctx->sew == MO_16)) {
>  uint32_t data = 0;
> -TCGLabel *over = gen_new_label();
>
>  gen_set_rm_chkfrm(ctx, RISCV_FRM_DYN);
> -tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over);
> -tcg_gen_brcond_tl(TCG_COND_GEU, cpu_vstart, cpu_vl, over);
>
>  data = FIELD_DP32(data, VDATA, VM, a->vm);
>  data = FIELD_DP32(data, VDATA, LMUL, ctx->lmul);
> @@ -116,7 +109,6 @@ static bool trans_vfwcvtbf16_f_f_v(DisasContext *ctx, 
> arg_vfwcvtbf16_f_f_v *a)
> ctx->cfg_ptr->vlenb, data,
> gen_helper_vfwcvtbf16_f_f_v);
>  mark_vs_dirty(ctx);
> -gen_set_label(over);
>  return true;
>  }
>  return false;
> @@ -130,11 +122,8 @@ static bool trans_vfwmaccbf16_vv(DisasContext *ctx, 
> arg_vfwmaccbf16_vv *a)
>  if (require_rvv(ctx) && vext_check_isa_ill(ctx) && (ctx->sew == MO_16) &&
>  vext_check_dss(ctx, a->rd, a->rs1, a->rs2, a->vm)) {
>  uint32_t data = 0;
> -TCGLabel *over = gen_new_label();
>
>  gen_set_rm_chkfrm(ctx, RISCV_FRM_DYN);
> -tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over);
> -tcg_gen_brcond_tl(TCG_COND_GEU, cpu_vstart, cpu_vl, over);
>
>  data = FIELD_DP32(data, VDATA, VM, a->vm);
>  data = FIELD_DP32(data, VDATA, LMUL, ctx->lmul);
> @@ -147,7 +136,6 @@ static bool trans_vfwmaccbf16_vv(DisasContext *ctx, 
> arg_vfwmaccbf16_vv *a)
> ctx->cfg_ptr->vlenb, data,
> gen_helper_vfwmaccbf16_vv);
>  mark_vs_dirty(ctx);
> -gen_set_label(over);
>  return true;
>  }
>  return false;
> diff --git a/target/riscv/insn_trans/trans_rvv.c.inc 
> b/target/riscv/insn_trans/trans_rvv.c.inc
> index 15ccebf3fc..58299d9bb8 100644
> --- a/target/riscv/insn_trans/trans_rvv.c.inc
> +++ b/target/riscv/insn_trans/trans_rvv.c.inc
> @@ -615,9 +615,6 @@ static bool ldst_us_trans(uint32_t vd, uint32_t rs1, 
> uint32_t data,
>  TCGv base;
>  TCGv_i32 desc;
>
> -TCGLabel *over = gen_new_label();
> -tcg_gen_brcond_tl(TCG_COND_GEU, cpu_vstart, cpu_vl, over);
> -
>  dest = tcg_temp_new_ptr();
>  mask = tcg_temp_new_ptr();
>  base = 

Re: [PATCH v6 2/9] trans_rvv.c.inc: remove 'is_store' bool from load/store fns

2024-03-05 Thread Alistair Francis
On Thu, Feb 22, 2024 at 7:34 AM Daniel Henrique Barboza
 wrote:
>
> After the 'mark_vs_dirty' changes from the previous patch the 'is_store'
> bool is unused in all load/store functions that were changed. Remove it.
>
> Signed-off-by: Daniel Henrique Barboza 
> Reviewed-by: Richard Henderson 
> Reviewed-by: Philippe Mathieu-Daudé 

Reviewed-by: Alistair Francis 

Alistair

> ---
>  target/riscv/insn_trans/trans_rvv.c.inc | 69 -
>  1 file changed, 34 insertions(+), 35 deletions(-)
>
> diff --git a/target/riscv/insn_trans/trans_rvv.c.inc 
> b/target/riscv/insn_trans/trans_rvv.c.inc
> index 7a98f1caa6..15ccebf3fc 100644
> --- a/target/riscv/insn_trans/trans_rvv.c.inc
> +++ b/target/riscv/insn_trans/trans_rvv.c.inc
> @@ -609,8 +609,7 @@ typedef void gen_helper_ldst_us(TCGv_ptr, TCGv_ptr, TCGv,
>  TCGv_env, TCGv_i32);
>
>  static bool ldst_us_trans(uint32_t vd, uint32_t rs1, uint32_t data,
> -  gen_helper_ldst_us *fn, DisasContext *s,
> -  bool is_store)
> +  gen_helper_ldst_us *fn, DisasContext *s)
>  {
>  TCGv_ptr dest, mask;
>  TCGv base;
> @@ -673,7 +672,7 @@ static bool ld_us_op(DisasContext *s, arg_r2nfvm *a, 
> uint8_t eew)
>  data = FIELD_DP32(data, VDATA, NF, a->nf);
>  data = FIELD_DP32(data, VDATA, VTA, s->vta);
>  data = FIELD_DP32(data, VDATA, VMA, s->vma);
> -return ldst_us_trans(a->rd, a->rs1, data, fn, s, false);
> +return ldst_us_trans(a->rd, a->rs1, data, fn, s);
>  }
>
>  static bool ld_us_check(DisasContext *s, arg_r2nfvm* a, uint8_t eew)
> @@ -710,7 +709,7 @@ static bool st_us_op(DisasContext *s, arg_r2nfvm *a, 
> uint8_t eew)
>  data = FIELD_DP32(data, VDATA, VM, a->vm);
>  data = FIELD_DP32(data, VDATA, LMUL, emul);
>  data = FIELD_DP32(data, VDATA, NF, a->nf);
> -return ldst_us_trans(a->rd, a->rs1, data, fn, s, true);
> +return ldst_us_trans(a->rd, a->rs1, data, fn, s);
>  }
>
>  static bool st_us_check(DisasContext *s, arg_r2nfvm* a, uint8_t eew)
> @@ -739,7 +738,7 @@ static bool ld_us_mask_op(DisasContext *s, arg_vlm_v *a, 
> uint8_t eew)
>  /* Mask destination register are always tail-agnostic */
>  data = FIELD_DP32(data, VDATA, VTA, s->cfg_vta_all_1s);
>  data = FIELD_DP32(data, VDATA, VMA, s->vma);
> -return ldst_us_trans(a->rd, a->rs1, data, fn, s, false);
> +return ldst_us_trans(a->rd, a->rs1, data, fn, s);
>  }
>
>  static bool ld_us_mask_check(DisasContext *s, arg_vlm_v *a, uint8_t eew)
> @@ -756,7 +755,7 @@ static bool st_us_mask_op(DisasContext *s, arg_vsm_v *a, 
> uint8_t eew)
>  /* EMUL = 1, NFIELDS = 1 */
>  data = FIELD_DP32(data, VDATA, LMUL, 0);
>  data = FIELD_DP32(data, VDATA, NF, 1);
> -return ldst_us_trans(a->rd, a->rs1, data, fn, s, true);
> +return ldst_us_trans(a->rd, a->rs1, data, fn, s);
>  }
>
>  static bool st_us_mask_check(DisasContext *s, arg_vsm_v *a, uint8_t eew)
> @@ -776,7 +775,7 @@ typedef void gen_helper_ldst_stride(TCGv_ptr, TCGv_ptr, 
> TCGv,
>
>  static bool ldst_stride_trans(uint32_t vd, uint32_t rs1, uint32_t rs2,
>uint32_t data, gen_helper_ldst_stride *fn,
> -  DisasContext *s, bool is_store)
> +  DisasContext *s)
>  {
>  TCGv_ptr dest, mask;
>  TCGv base, stride;
> @@ -823,7 +822,7 @@ static bool ld_stride_op(DisasContext *s, arg_rnfvm *a, 
> uint8_t eew)
>  data = FIELD_DP32(data, VDATA, NF, a->nf);
>  data = FIELD_DP32(data, VDATA, VTA, s->vta);
>  data = FIELD_DP32(data, VDATA, VMA, s->vma);
> -return ldst_stride_trans(a->rd, a->rs1, a->rs2, data, fn, s, false);
> +return ldst_stride_trans(a->rd, a->rs1, a->rs2, data, fn, s);
>  }
>
>  static bool ld_stride_check(DisasContext *s, arg_rnfvm* a, uint8_t eew)
> @@ -857,7 +856,7 @@ static bool st_stride_op(DisasContext *s, arg_rnfvm *a, 
> uint8_t eew)
>  return false;
>  }
>
> -return ldst_stride_trans(a->rd, a->rs1, a->rs2, data, fn, s, true);
> +return ldst_stride_trans(a->rd, a->rs1, a->rs2, data, fn, s);
>  }
>
>  static bool st_stride_check(DisasContext *s, arg_rnfvm* a, uint8_t eew)
> @@ -880,7 +879,7 @@ typedef void gen_helper_ldst_index(TCGv_ptr, TCGv_ptr, 
> TCGv,
>
>  static bool ldst_index_trans(uint32_t vd, uint32_t rs1, uint32_t vs2,
>   uint32_t data, gen_helper_ldst_index *fn,
> - DisasContext *s, bool is_store)
> + DisasContext *s)
>  {
>  TCGv_ptr dest, mask, index;
>  TCGv base;
> @@ -947,7 +946,7 @@ static bool ld_index_op(DisasContext *s, arg_rnfvm *a, 
> uint8_t eew)
>  data = FIELD_DP32(data, VDATA, NF, a->nf);
>  data = FIELD_DP32(data, VDATA, VTA, s->vta);
>  data = FIELD_DP32(data, VDATA, VMA, s->vma);
> -return ldst_index_trans(a->rd, a->rs1, a->rs2, data, fn, s, false);
> +return ldst_index_trans(a->rd, a->rs1, 

Re: [PATCH v6 1/9] trans_rvv.c.inc: mark_vs_dirty() before loads and stores

2024-03-05 Thread Alistair Francis
On Thu, Feb 22, 2024 at 7:34 AM Daniel Henrique Barboza
 wrote:
>
> While discussing a problem with how we're (not) setting vstart_eq_zero
> Richard had the following to say w.r.t the conditional mark_vs_dirty()
> calls on load/store functions [1]:
>
> "I think it's required to have stores set dirty unconditionally, before
> the operation.
>
> Consider a store that traps on the 2nd element, leaving vstart = 2, and
> exiting to the main loop via exception. The exception enters the kernel
> page fault handler. The kernel may need to fault in the page for the
> process, and in the meantime task switch.
>
> If vs dirty is not already set, the kernel won't know to save vector
> state on task switch."
>
> Do a mark_vs_dirty() before both loads and stores.
>
> [1] 
> https://lore.kernel.org/qemu-riscv/72c7503b-0f43-44b8-aa82-fbafed2aa...@linaro.org/
>
> Suggested-by: Richard Henderson 
> Signed-off-by: Daniel Henrique Barboza 
> Reviewed-by: Richard Henderson 

Reviewed-by: Alistair Francis 

Alistair

> ---
>  target/riscv/insn_trans/trans_rvv.c.inc | 23 ---
>  1 file changed, 8 insertions(+), 15 deletions(-)
>
> diff --git a/target/riscv/insn_trans/trans_rvv.c.inc 
> b/target/riscv/insn_trans/trans_rvv.c.inc
> index 9e101ab434..7a98f1caa6 100644
> --- a/target/riscv/insn_trans/trans_rvv.c.inc
> +++ b/target/riscv/insn_trans/trans_rvv.c.inc
> @@ -636,11 +636,9 @@ static bool ldst_us_trans(uint32_t vd, uint32_t rs1, 
> uint32_t data,
>  tcg_gen_addi_ptr(dest, tcg_env, vreg_ofs(s, vd));
>  tcg_gen_addi_ptr(mask, tcg_env, vreg_ofs(s, 0));
>
> -fn(dest, mask, base, tcg_env, desc);
> +mark_vs_dirty(s);
>
> -if (!is_store) {
> -mark_vs_dirty(s);
> -}
> +fn(dest, mask, base, tcg_env, desc);
>
>  gen_set_label(over);
>  return true;
> @@ -797,11 +795,9 @@ static bool ldst_stride_trans(uint32_t vd, uint32_t rs1, 
> uint32_t rs2,
>  tcg_gen_addi_ptr(dest, tcg_env, vreg_ofs(s, vd));
>  tcg_gen_addi_ptr(mask, tcg_env, vreg_ofs(s, 0));
>
> -fn(dest, mask, base, stride, tcg_env, desc);
> +mark_vs_dirty(s);
>
> -if (!is_store) {
> -mark_vs_dirty(s);
> -}
> +fn(dest, mask, base, stride, tcg_env, desc);
>
>  gen_set_label(over);
>  return true;
> @@ -904,11 +900,9 @@ static bool ldst_index_trans(uint32_t vd, uint32_t rs1, 
> uint32_t vs2,
>  tcg_gen_addi_ptr(index, tcg_env, vreg_ofs(s, vs2));
>  tcg_gen_addi_ptr(mask, tcg_env, vreg_ofs(s, 0));
>
> -fn(dest, mask, base, index, tcg_env, desc);
> +mark_vs_dirty(s);
>
> -if (!is_store) {
> -mark_vs_dirty(s);
> -}
> +fn(dest, mask, base, index, tcg_env, desc);
>
>  gen_set_label(over);
>  return true;
> @@ -1102,11 +1096,10 @@ static bool ldst_whole_trans(uint32_t vd, uint32_t 
> rs1, uint32_t nf,
>  base = get_gpr(s, rs1, EXT_NONE);
>  tcg_gen_addi_ptr(dest, tcg_env, vreg_ofs(s, vd));
>
> +mark_vs_dirty(s);
> +
>  fn(dest, base, tcg_env, desc);
>
> -if (!is_store) {
> -mark_vs_dirty(s);
> -}
>  gen_set_label(over);
>
>  return true;
> --
> 2.43.2
>
>



Re: [PATCH v3] target/loongarch: Add TCG macro in structure CPUArchState

2024-03-05 Thread maobibo




On 2024/3/5 下午11:45, Richard Henderson wrote:

On 3/4/24 20:26, Bibo Mao wrote:

+#ifdef CONFIG_TCG
  static int loongarch_map_tlb_entry(CPULoongArchState *env, hwaddr 
*physical,

 int *prot, target_ulong address,
 int access_type, int index, int 
mmu_idx)
@@ -154,6 +155,14 @@ static int 
loongarch_map_address(CPULoongArchState *env, hwaddr *physical,

  return TLBRET_NOMATCH;
  }
+#else
+static int loongarch_map_address(CPULoongArchState *env, hwaddr 
*physical,

+ int *prot, target_ulong address,
+ MMUAccessType access_type, int mmu_idx)
+{
+    return TLBRET_NOMATCH;
+}
+#endif


You may find that debugging with gdbstub or the qemu monitor easier with 
a routine that walks page tables for loongarch_cpu_get_phys_page_debug.  
For kvm, the existing code is insufficient anyway, because you'd need to 
emulate a hardware page table walk, not use env->tlb[], which would not 
be populated.


This can be improved later.
Sure, will add page table walk emulation code later in function 
loongarch_cpu_get_phys_page_debug(). And thanks for your guidance.


Regards
Bibo Mao


Reviewed-by: Richard Henderson 


r~





RE: [PATCH v4 2/8] migration/multifd: add get_iov_count in the multifd method

2024-03-05 Thread Liu, Yuan1
> -Original Message-
> From: Fabiano Rosas 
> Sent: Wednesday, March 6, 2024 4:24 AM
> To: Liu, Yuan1 ; pet...@redhat.com
> Cc: qemu-devel@nongnu.org; hao.xi...@bytedance.com;
> bryan.zh...@bytedance.com; Liu, Yuan1 ; Zou, Nanhai
> 
> Subject: Re: [PATCH v4 2/8] migration/multifd: add get_iov_count in the
> multifd method
> 
> Yuan Liu  writes:
> 
> > the new function get_iov_count is used to get the number of
> > IOVs required by a specified multifd method
> >
> > Different multifd methods may require different numbers of IOVs.
> > Based on streaming compression of zlib and zstd, all pages will be
> > compressed to a data block, so an IOV is required to send this data
> > block. For no compression, each IOV is used to send a page, so the
> > number of IOVs required is the same as the number of pages.
> 
> Let's just move the responsibility of allocating p->iov to the client
> code. You can move the allocation into send_setup() and the free into
> send_cleanup().

Yes, this is a good way, I will implement it in the next version

> >
> > Signed-off-by: Yuan Liu 
> > Reviewed-by: Nanhai Zou 
> > ---
> >  migration/multifd-zlib.c | 18 +-
> >  migration/multifd-zstd.c | 18 +-
> >  migration/multifd.c  | 24 +---
> >  migration/multifd.h  |  2 ++
> >  4 files changed, 57 insertions(+), 5 deletions(-)
> >
> > diff --git a/migration/multifd-zlib.c b/migration/multifd-zlib.c
> > index 012e3bdea1..35187f2aff 100644
> > --- a/migration/multifd-zlib.c
> > +++ b/migration/multifd-zlib.c
> > @@ -313,13 +313,29 @@ static int zlib_recv_pages(MultiFDRecvParams *p,
> Error **errp)
> >  return 0;
> >  }
> >
> > +/**
> > + * zlib_get_iov_count: get the count of IOVs
> > + *
> > + * For zlib streaming compression, all pages will be compressed into a
> data
> > + * block, and an IOV is requested for sending this block.
> > + *
> > + * Returns the count of the IOVs
> > + *
> > + * @page_count: Indicate the maximum count of pages processed by
> multifd
> > + */
> > +static uint32_t zlib_get_iov_count(uint32_t page_count)
> > +{
> > +return 1;
> > +}
> > +
> >  static MultiFDMethods multifd_zlib_ops = {
> >  .send_setup = zlib_send_setup,
> >  .send_cleanup = zlib_send_cleanup,
> >  .send_prepare = zlib_send_prepare,
> >  .recv_setup = zlib_recv_setup,
> >  .recv_cleanup = zlib_recv_cleanup,
> > -.recv_pages = zlib_recv_pages
> > +.recv_pages = zlib_recv_pages,
> > +.get_iov_count = zlib_get_iov_count
> >  };
> >
> >  static void multifd_zlib_register(void)
> > diff --git a/migration/multifd-zstd.c b/migration/multifd-zstd.c
> > index dc8fe43e94..25ed1add2a 100644
> > --- a/migration/multifd-zstd.c
> > +++ b/migration/multifd-zstd.c
> > @@ -304,13 +304,29 @@ static int zstd_recv_pages(MultiFDRecvParams *p,
> Error **errp)
> >  return 0;
> >  }
> >
> > +/**
> > + * zstd_get_iov_count: get the count of IOVs
> > + *
> > + * For zstd streaming compression, all pages will be compressed into a
> data
> > + * block, and an IOV is requested for sending this block.
> > + *
> > + * Returns the count of the IOVs
> > + *
> > + * @page_count: Indicate the maximum count of pages processed by
> multifd
> > + */
> > +static uint32_t zstd_get_iov_count(uint32_t page_count)
> > +{
> > +return 1;
> > +}
> > +
> >  static MultiFDMethods multifd_zstd_ops = {
> >  .send_setup = zstd_send_setup,
> >  .send_cleanup = zstd_send_cleanup,
> >  .send_prepare = zstd_send_prepare,
> >  .recv_setup = zstd_recv_setup,
> >  .recv_cleanup = zstd_recv_cleanup,
> > -.recv_pages = zstd_recv_pages
> > +.recv_pages = zstd_recv_pages,
> > +.get_iov_count = zstd_get_iov_count
> >  };
> >
> >  static void multifd_zstd_register(void)
> > diff --git a/migration/multifd.c b/migration/multifd.c
> > index adfe8c9a0a..787402247e 100644
> > --- a/migration/multifd.c
> > +++ b/migration/multifd.c
> > @@ -209,13 +209,29 @@ static int nocomp_recv_pages(MultiFDRecvParams *p,
> Error **errp)
> >  return qio_channel_readv_all(p->c, p->iov, p->normal_num, errp);
> >  }
> >
> > +/**
> > + * nocomp_get_iov_count: get the count of IOVs
> > + *
> > + * For no compression, the count of IOVs required is the same as the
> count of
> > + * pages
> > + *
> > + * Returns the count of the IOVs
> > + *
> > + * @page_count: Indicate the maximum count of pages processed by
> multifd
> > + */
> > +static uint32_t nocomp_get_iov_count(uint32_t page_count)
> > +{
> > +return page_count;
> > +}
> > +
> >  static MultiFDMethods multifd_nocomp_ops = {
> >  .send_setup = nocomp_send_setup,
> >  .send_cleanup = nocomp_send_cleanup,
> >  .send_prepare = nocomp_send_prepare,
> >  .recv_setup = nocomp_recv_setup,
> >  .recv_cleanup = nocomp_recv_cleanup,
> > -.recv_pages = nocomp_recv_pages
> > +.recv_pages = nocomp_recv_pages,
> > +.get_iov_count = nocomp_get_iov_count
> >  };
> >
> >  static MultiFDMethods 

  1   2   3   4   >