Re: [PATCH v2 2/3] hw/acpi: Upgrade ACPI SPCR table to support SPCR table version 4 format

2024-05-12 Thread Sunil V L
Hi Sia Jee Heng,

On Mon, May 06, 2024 at 10:22:11PM -0700, Sia Jee Heng wrote:
> Update the SPCR table to accommodate the SPCR Table version 4 [1].
> The SPCR table has been modified to adhere to the version 4 format [2].
> 
> [1]: 
> https://learn.microsoft.com/en-us/windows-hardware/drivers/serports/serial-port-console-redirection-table
> [2]: https://github.com/acpica/acpica/pull/931
> 
> Signed-off-by: Sia Jee Heng 
> ---
>  hw/acpi/aml-build.c | 14 +++---
>  hw/arm/virt-acpi-build.c| 10 --
>  hw/riscv/virt-acpi-build.c  | 12 +---
>  include/hw/acpi/acpi-defs.h |  7 +--
>  include/hw/acpi/aml-build.h |  2 +-
>  5 files changed, 34 insertions(+), 11 deletions(-)
> 
> diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c
> index 6d4517cfbe..7c43573eef 100644
> --- a/hw/acpi/aml-build.c
> +++ b/hw/acpi/aml-build.c
> @@ -1996,7 +1996,7 @@ static void build_processor_hierarchy_node(GArray *tbl, 
> uint32_t flags,
>  
>  void build_spcr(GArray *table_data, BIOSLinker *linker,
>  const AcpiSpcrData *f, const uint8_t rev,
> -const char *oem_id, const char *oem_table_id)
> +const char *oem_id, const char *oem_table_id, const char 
> *name)
>  {
>  AcpiTable table = { .sig = "SPCR", .rev = rev, .oem_id = oem_id,
>  .oem_table_id = oem_table_id };
> @@ -2042,8 +2042,16 @@ void build_spcr(GArray *table_data, BIOSLinker *linker,
>  build_append_int_noprefix(table_data, f->pci_flags, 4);
>  /* PCI Segment */
>  build_append_int_noprefix(table_data, f->pci_segment, 1);
> -/* Reserved */
> -build_append_int_noprefix(table_data, 0, 4);
> +/* UartClkFreq */
> +build_append_int_noprefix(table_data, f->uart_clk_freq, 4);
> +/* PreciseBaudrate */
> +build_append_int_noprefix(table_data, f->precise_baudrate, 4);
> +/* NameSpaceStringLength */
> +build_append_int_noprefix(table_data, f->namespace_string_length, 2);
> +/* NameSpaceStringOffset */
> +build_append_int_noprefix(table_data, f->namespace_string_offset, 2);
> +/* NamespaceString[] */
> +g_array_append_vals(table_data, name, f->namespace_string_length);
>  
Is it possible to check the revision here and add new fields only if the
revision supports it? ARM maintainers are better to comment but IMO, we
better keep ARM's SPCR in the same current version since I don't know
how consumers like linux (and other OSs) react to the change.

Thanks!
Sunil
>  acpi_table_end(linker, );
>  }
> diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
> index 6a1bde61ce..cb345e8659 100644
> --- a/hw/arm/virt-acpi-build.c
> +++ b/hw/arm/virt-acpi-build.c
> @@ -428,11 +428,12 @@ build_iort(GArray *table_data, BIOSLinker *linker, 
> VirtMachineState *vms)
>  
>  /*
>   * Serial Port Console Redirection Table (SPCR)
> - * Rev: 1.07
> + * Rev: 1.10
>   */
>  static void
>  spcr_setup(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
>  {
> +const char name[] = ".";
>  AcpiSpcrData serial = {
>  .interface_type = 3,   /* ARM PL011 UART */
>  .base_addr.id = AML_AS_SYSTEM_MEMORY,
> @@ -456,9 +457,14 @@ spcr_setup(GArray *table_data, BIOSLinker *linker, 
> VirtMachineState *vms)
>  .pci_function = 0,
>  .pci_flags = 0,
>  .pci_segment = 0,
> +.uart_clk_freq = 0,
> +.precise_baudrate = 0,
> +.namespace_string_length = sizeof(name),
> +.namespace_string_offset = 88,
>  };
>  
> -build_spcr(table_data, linker, , 2, vms->oem_id, 
> vms->oem_table_id);
> +build_spcr(table_data, linker, , 4, vms->oem_id, 
> vms->oem_table_id,
> +   name);
>  }
>  
>  /*
> diff --git a/hw/riscv/virt-acpi-build.c b/hw/riscv/virt-acpi-build.c
> index 0925528160..5fa3942491 100644
> --- a/hw/riscv/virt-acpi-build.c
> +++ b/hw/riscv/virt-acpi-build.c
> @@ -176,14 +176,15 @@ acpi_dsdt_add_uart(Aml *scope, const MemMapEntry 
> *uart_memmap,
>  
>  /*
>   * Serial Port Console Redirection Table (SPCR)
> - * Rev: 1.07
> + * Rev: 1.10
>   */
>  
>  static void
>  spcr_setup(GArray *table_data, BIOSLinker *linker, RISCVVirtState *s)
>  {
> +const char name[] = ".";
>  AcpiSpcrData serial = {
> -.interface_type = 0,   /* 16550 compatible */
> +.interface_type = 0x12,   /* 16550 compatible */
>  .base_addr.id = AML_AS_SYSTEM_MEMORY,
>  .base_addr.width = 32,
>  .base_addr.offset = 0,
> @@ -205,9 +206,14 @@ spcr_setup(GArray *table_data, BIOSLinker *linker, 
> RISCVVirtState *s)
>  .pci_function = 0,
>  .pci_flags = 0,
>  .pci_segment = 0,
> +.uart_clk_freq = 0,
> +.precise_baudrate = 0,
> +.namespace_string_length = sizeof(name),
> +.namespace_string_offset = 88,
>  };
>  
> -build_spcr(table_data, linker, , 2, s->oem_id, s->oem_table_id);
> +build_spcr(table_data, linker, , 4, s->oem_id, 

Re: [PATCH v2 2/3] hw/acpi: Upgrade ACPI SPCR table to support SPCR table version 4 format

2024-05-12 Thread Alistair Francis
On Tue, May 7, 2024 at 3:24 PM Sia Jee Heng
 wrote:
>
> Update the SPCR table to accommodate the SPCR Table version 4 [1].
> The SPCR table has been modified to adhere to the version 4 format [2].
>
> [1]: 
> https://learn.microsoft.com/en-us/windows-hardware/drivers/serports/serial-port-console-redirection-table
> [2]: https://github.com/acpica/acpica/pull/931
>
> Signed-off-by: Sia Jee Heng 

Acked-by: Alistair Francis 

Alistair

> ---
>  hw/acpi/aml-build.c | 14 +++---
>  hw/arm/virt-acpi-build.c| 10 --
>  hw/riscv/virt-acpi-build.c  | 12 +---
>  include/hw/acpi/acpi-defs.h |  7 +--
>  include/hw/acpi/aml-build.h |  2 +-
>  5 files changed, 34 insertions(+), 11 deletions(-)
>
> diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c
> index 6d4517cfbe..7c43573eef 100644
> --- a/hw/acpi/aml-build.c
> +++ b/hw/acpi/aml-build.c
> @@ -1996,7 +1996,7 @@ static void build_processor_hierarchy_node(GArray *tbl, 
> uint32_t flags,
>
>  void build_spcr(GArray *table_data, BIOSLinker *linker,
>  const AcpiSpcrData *f, const uint8_t rev,
> -const char *oem_id, const char *oem_table_id)
> +const char *oem_id, const char *oem_table_id, const char 
> *name)
>  {
>  AcpiTable table = { .sig = "SPCR", .rev = rev, .oem_id = oem_id,
>  .oem_table_id = oem_table_id };
> @@ -2042,8 +2042,16 @@ void build_spcr(GArray *table_data, BIOSLinker *linker,
>  build_append_int_noprefix(table_data, f->pci_flags, 4);
>  /* PCI Segment */
>  build_append_int_noprefix(table_data, f->pci_segment, 1);
> -/* Reserved */
> -build_append_int_noprefix(table_data, 0, 4);
> +/* UartClkFreq */
> +build_append_int_noprefix(table_data, f->uart_clk_freq, 4);
> +/* PreciseBaudrate */
> +build_append_int_noprefix(table_data, f->precise_baudrate, 4);
> +/* NameSpaceStringLength */
> +build_append_int_noprefix(table_data, f->namespace_string_length, 2);
> +/* NameSpaceStringOffset */
> +build_append_int_noprefix(table_data, f->namespace_string_offset, 2);
> +/* NamespaceString[] */
> +g_array_append_vals(table_data, name, f->namespace_string_length);
>
>  acpi_table_end(linker, );
>  }
> diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
> index 6a1bde61ce..cb345e8659 100644
> --- a/hw/arm/virt-acpi-build.c
> +++ b/hw/arm/virt-acpi-build.c
> @@ -428,11 +428,12 @@ build_iort(GArray *table_data, BIOSLinker *linker, 
> VirtMachineState *vms)
>
>  /*
>   * Serial Port Console Redirection Table (SPCR)
> - * Rev: 1.07
> + * Rev: 1.10
>   */
>  static void
>  spcr_setup(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
>  {
> +const char name[] = ".";
>  AcpiSpcrData serial = {
>  .interface_type = 3,   /* ARM PL011 UART */
>  .base_addr.id = AML_AS_SYSTEM_MEMORY,
> @@ -456,9 +457,14 @@ spcr_setup(GArray *table_data, BIOSLinker *linker, 
> VirtMachineState *vms)
>  .pci_function = 0,
>  .pci_flags = 0,
>  .pci_segment = 0,
> +.uart_clk_freq = 0,
> +.precise_baudrate = 0,
> +.namespace_string_length = sizeof(name),
> +.namespace_string_offset = 88,
>  };
>
> -build_spcr(table_data, linker, , 2, vms->oem_id, 
> vms->oem_table_id);
> +build_spcr(table_data, linker, , 4, vms->oem_id, 
> vms->oem_table_id,
> +   name);
>  }
>
>  /*
> diff --git a/hw/riscv/virt-acpi-build.c b/hw/riscv/virt-acpi-build.c
> index 0925528160..5fa3942491 100644
> --- a/hw/riscv/virt-acpi-build.c
> +++ b/hw/riscv/virt-acpi-build.c
> @@ -176,14 +176,15 @@ acpi_dsdt_add_uart(Aml *scope, const MemMapEntry 
> *uart_memmap,
>
>  /*
>   * Serial Port Console Redirection Table (SPCR)
> - * Rev: 1.07
> + * Rev: 1.10
>   */
>
>  static void
>  spcr_setup(GArray *table_data, BIOSLinker *linker, RISCVVirtState *s)
>  {
> +const char name[] = ".";
>  AcpiSpcrData serial = {
> -.interface_type = 0,   /* 16550 compatible */
> +.interface_type = 0x12,   /* 16550 compatible */
>  .base_addr.id = AML_AS_SYSTEM_MEMORY,
>  .base_addr.width = 32,
>  .base_addr.offset = 0,
> @@ -205,9 +206,14 @@ spcr_setup(GArray *table_data, BIOSLinker *linker, 
> RISCVVirtState *s)
>  .pci_function = 0,
>  .pci_flags = 0,
>  .pci_segment = 0,
> +.uart_clk_freq = 0,
> +.precise_baudrate = 0,
> +.namespace_string_length = sizeof(name),
> +.namespace_string_offset = 88,
>  };
>
> -build_spcr(table_data, linker, , 2, s->oem_id, s->oem_table_id);
> +build_spcr(table_data, linker, , 4, s->oem_id, s->oem_table_id,
> +   name);
>  }
>
>  /* RHCT Node[N] starts at offset 56 */
> diff --git a/include/hw/acpi/acpi-defs.h b/include/hw/acpi/acpi-defs.h
> index 0e6e82b339..2e6e341998 100644
> --- a/include/hw/acpi/acpi-defs.h
> +++ b/include/hw/acpi/acpi-defs.h
> @@ -112,7 +112,6 @@ typedef 

Re: [PATCH v2] Re-enable riscv64-debian-cross-container (debian riscv64 is finally usable again!)

2024-05-12 Thread Alistair Francis
On Fri, May 3, 2024 at 5:17 PM Michael Tokarev  wrote:
>
> Revert "gitlab-ci: Disable the riscv64-debian-cross-container by default"
> This reverts commit f51f90c65ed7706c3c4f7a889ce3d6b7ab75ef6a.
>
> riscv64 in debian has been non-functioning for almost a year, after the
> architecture has been promoted to release architecture and all binary
> packages started to be re-built, making the port not multi-arch-co-installable
> for a long time (in debian, multi-arch packages must be of the same version,
> but when a package is rebuilt on one architecture it gets a version bump too).
> Later on, debiah had a long time64_t transition which made sid unusable for
> quite some time too.  Both such events happens in debian very rarely (like,
> once in 10 years or so - for example, previous big transition like that was
> libc5 => libc6 transition).  Now both of these are finished (where qemu is
> concerned anyway).
>
> Hopefully debian unstable wont be very unstable.  At the very least it is
> better to have sporadic CI failures here than no riscv64 coverage at all.
>
> Signed-off-by: Michael Tokarev 

Acked-by: Alistair Francis 

Alistair

> ---
> v2: drop a TODO comment which turned out to be confused, replacing it
>  with the description why debian riscv64 were unusable.
>
>  .gitlab-ci.d/container-cross.yml | 1 -
>  1 file changed, 1 deletion(-)
>
> diff --git a/.gitlab-ci.d/container-cross.yml 
> b/.gitlab-ci.d/container-cross.yml
> index e3103940a0..dbffed3f21 100644
> --- a/.gitlab-ci.d/container-cross.yml
> +++ b/.gitlab-ci.d/container-cross.yml
> @@ -77,7 +77,6 @@ riscv64-debian-cross-container:
>allow_failure: true
>variables:
>  NAME: debian-riscv64-cross
> -QEMU_JOB_OPTIONAL: 1
>
>  s390x-debian-cross-container:
>extends: .container_job_template
> --
> 2.39.2
>
>



Re: [PATCH v2 1/3] qtest: allow SPCR acpi table changes

2024-05-12 Thread Alistair Francis
On Tue, May 7, 2024 at 3:24 PM Sia Jee Heng
 wrote:

Can you describe why you are doing this and that it will be reverted
in the commit message?

Alistair

>
> Signed-off-by: Sia Jee Heng 
> ---
>  tests/qtest/bios-tables-test-allowed-diff.h | 2 ++
>  1 file changed, 2 insertions(+)
>
> diff --git a/tests/qtest/bios-tables-test-allowed-diff.h 
> b/tests/qtest/bios-tables-test-allowed-diff.h
> index dfb8523c8b..3f12ca546b 100644
> --- a/tests/qtest/bios-tables-test-allowed-diff.h
> +++ b/tests/qtest/bios-tables-test-allowed-diff.h
> @@ -1 +1,3 @@
>  /* List of comma-separated changed AML files to ignore */
> +"tests/data/acpi/virt/riscv64/SPCR",
> +"tests/data/acpi/virt/aarch64/SPCR",
> --
> 2.34.1
>
>



[PATCH v2 06/11] block/nvme: add reservation command protocol constants

2024-05-12 Thread Changqi Lu
Add constants for the NVMe persistent command protocol.
The constants include the reservation command opcode and
reservation type values defined in section 7 of the NVMe
2.0 specification.

Signed-off-by: Changqi Lu 
Signed-off-by: zhenwei pi 
---
 include/block/nvme.h | 55 
 1 file changed, 55 insertions(+)

diff --git a/include/block/nvme.h b/include/block/nvme.h
index bb231d0b9a..42e8b43408 100644
--- a/include/block/nvme.h
+++ b/include/block/nvme.h
@@ -633,6 +633,10 @@ enum NvmeIoCommands {
 NVME_CMD_WRITE_ZEROES   = 0x08,
 NVME_CMD_DSM= 0x09,
 NVME_CMD_VERIFY = 0x0c,
+NVME_CMD_RESV_REGISTER  = 0x0d,
+NVME_CMD_RESV_REPORT= 0x0e,
+NVME_CMD_RESV_ACQUIRE   = 0x11,
+NVME_CMD_RESV_RELEASE   = 0x15,
 NVME_CMD_IO_MGMT_RECV   = 0x12,
 NVME_CMD_COPY   = 0x19,
 NVME_CMD_IO_MGMT_SEND   = 0x1d,
@@ -641,6 +645,57 @@ enum NvmeIoCommands {
 NVME_CMD_ZONE_APPEND= 0x7d,
 };
 
+typedef enum {
+NVME_RESV_REGISTER_ACTION_REGISTER  = 0x00,
+NVME_RESV_REGISTER_ACTION_UNREGISTER= 0x01,
+NVME_RESV_REGISTER_ACTION_REPLACE   = 0x02,
+} NVME_RESV_REGISTER_ACTION;
+
+typedef enum {
+NVME_RESV_RELEASE_ACTION_RELEASE= 0x00,
+NVME_RESV_RELEASE_ACTION_CLEAR  = 0x01,
+} NVME_RESV_RELEASE_ACTION;
+
+typedef enum {
+NVME_RESV_ACQUIRE_ACTION_ACQUIRE= 0x00,
+NVME_RESV_ACQUIRE_ACTION_PREEMPT= 0x01,
+NVME_RESV_ACQUIRE_ACTION_PREEMPT_AND_ABORT  = 0x02,
+} NVME_RESV_ACQUIRE_ACTION;
+
+typedef enum {
+NVME_RESV_WRITE_EXCLUSIVE   = 0x01,
+NVME_RESV_EXCLUSIVE_ACCESS  = 0x02,
+NVME_RESV_WRITE_EXCLUSIVE_REGS_ONLY = 0x03,
+NVME_RESV_EXCLUSIVE_ACCESS_REGS_ONLY= 0x04,
+NVME_RESV_WRITE_EXCLUSIVE_ALL_REGS  = 0x05,
+NVME_RESV_EXCLUSIVE_ACCESS_ALL_REGS = 0x06,
+} NVMEResvType;
+
+typedef enum NVMEPrCap {
+/* Persist Through Power Loss */
+NVME_PR_CAP_PTPL = 1 << 0,
+/* Write Exclusive reservation type */
+NVME_PR_CAP_WR_EX = 1 << 1,
+/* Exclusive Access reservation type */
+NVME_PR_CAP_EX_AC = 1 << 2,
+/* Write Exclusive Registrants Only reservation type */
+NVME_PR_CAP_WR_EX_RO = 1 << 3,
+/* Exclusive Access Registrants Only reservation type */
+NVME_PR_CAP_EX_AC_RO = 1 << 4,
+/* Write Exclusive All Registrants reservation type */
+NVME_PR_CAP_WR_EX_AR = 1 << 5,
+/* Exclusive Access All Registrants reservation type */
+NVME_PR_CAP_EX_AC_AR = 1 << 6,
+
+NVME_PR_CAP_ALL = (NVME_PR_CAP_PTPL |
+  NVME_PR_CAP_WR_EX |
+  NVME_PR_CAP_EX_AC |
+  NVME_PR_CAP_WR_EX_RO |
+  NVME_PR_CAP_EX_AC_RO |
+  NVME_PR_CAP_WR_EX_AR |
+  NVME_PR_CAP_EX_AC_AR),
+} NVMEPrCap;
+
 typedef struct QEMU_PACKED NvmeDeleteQ {
 uint8_t opcode;
 uint8_t flags;
-- 
2.20.1




[PATCH v2 04/11] scsi/util: add helper functions for persistent reservation types conversion

2024-05-12 Thread Changqi Lu
This commit introduces two helper functions
that facilitate the conversion between the
persistent reservation types used in the SCSI
protocol and those used in the block layer.

Signed-off-by: Changqi Lu 
Signed-off-by: zhenwei pi 
---
 include/scsi/utils.h |  8 +
 scsi/utils.c | 77 
 2 files changed, 85 insertions(+)

diff --git a/include/scsi/utils.h b/include/scsi/utils.h
index d5c8efa16e..89a0b082fb 100644
--- a/include/scsi/utils.h
+++ b/include/scsi/utils.h
@@ -1,6 +1,8 @@
 #ifndef SCSI_UTILS_H
 #define SCSI_UTILS_H
 
+#include "block/block-common.h"
+#include "scsi/constants.h"
 #ifdef CONFIG_LINUX
 #include 
 #endif
@@ -135,6 +137,12 @@ uint32_t scsi_data_cdb_xfer(uint8_t *buf);
 uint32_t scsi_cdb_xfer(uint8_t *buf);
 int scsi_cdb_length(uint8_t *buf);
 
+BlockPrType scsi_pr_type_to_block(SCSIPrType type);
+SCSIPrType block_pr_type_to_scsi(BlockPrType type);
+
+uint8_t scsi_pr_cap_to_block(uint16_t scsi_pr_cap);
+uint16_t block_pr_cap_to_scsi(uint8_t block_pr_cap);
+
 /* Linux SG_IO interface.  */
 #ifdef CONFIG_LINUX
 #define SG_ERR_DRIVER_TIMEOUT  0x06
diff --git a/scsi/utils.c b/scsi/utils.c
index 357b036671..f1b63f9196 100644
--- a/scsi/utils.c
+++ b/scsi/utils.c
@@ -658,3 +658,80 @@ int scsi_sense_from_host_status(uint8_t host_status,
 }
 return GOOD;
 }
+
+BlockPrType scsi_pr_type_to_block(SCSIPrType type)
+{
+switch (type) {
+case SCSI_PR_WRITE_EXCLUSIVE:
+return BLK_PR_WRITE_EXCLUSIVE;
+case SCSI_PR_EXCLUSIVE_ACCESS:
+return BLK_PR_EXCLUSIVE_ACCESS;
+case SCSI_PR_WRITE_EXCLUSIVE_REGS_ONLY:
+return BLK_PR_WRITE_EXCLUSIVE_REGS_ONLY;
+case SCSI_PR_EXCLUSIVE_ACCESS_REGS_ONLY:
+return BLK_PR_EXCLUSIVE_ACCESS_REGS_ONLY;
+case SCSI_PR_WRITE_EXCLUSIVE_ALL_REGS:
+return BLK_PR_WRITE_EXCLUSIVE_ALL_REGS;
+case SCSI_PR_EXCLUSIVE_ACCESS_ALL_REGS:
+return BLK_PR_EXCLUSIVE_ACCESS_ALL_REGS;
+}
+
+return 0;
+}
+
+SCSIPrType block_pr_type_to_scsi(BlockPrType type)
+{
+switch (type) {
+case BLK_PR_WRITE_EXCLUSIVE:
+return SCSI_PR_WRITE_EXCLUSIVE;
+case BLK_PR_EXCLUSIVE_ACCESS:
+return SCSI_PR_EXCLUSIVE_ACCESS;
+case BLK_PR_WRITE_EXCLUSIVE_REGS_ONLY:
+return SCSI_PR_WRITE_EXCLUSIVE_REGS_ONLY;
+case BLK_PR_EXCLUSIVE_ACCESS_REGS_ONLY:
+return SCSI_PR_EXCLUSIVE_ACCESS_REGS_ONLY;
+case BLK_PR_WRITE_EXCLUSIVE_ALL_REGS:
+return SCSI_PR_WRITE_EXCLUSIVE_ALL_REGS;
+case BLK_PR_EXCLUSIVE_ACCESS_ALL_REGS:
+return SCSI_PR_EXCLUSIVE_ACCESS_ALL_REGS;
+}
+
+return 0;
+}
+
+
+uint8_t scsi_pr_cap_to_block(uint16_t scsi_pr_cap)
+{
+uint8_t res = 0;
+res |= (scsi_pr_cap & SCSI_PR_CAP_WR_EX) ?
+   BLK_PR_CAP_WR_EX : 0;
+res |= (scsi_pr_cap & SCSI_PR_CAP_EX_AC) ?
+   BLK_PR_CAP_EX_AC : 0;
+res |= (scsi_pr_cap & SCSI_PR_CAP_WR_EX_RO) ?
+   BLK_PR_CAP_WR_EX_RO : 0;
+res |= (scsi_pr_cap & SCSI_PR_CAP_EX_AC_RO) ?
+   BLK_PR_CAP_EX_AC_RO : 0;
+res |= (scsi_pr_cap & SCSI_PR_CAP_WR_EX_AR) ?
+   BLK_PR_CAP_WR_EX_AR : 0;
+res |= (scsi_pr_cap & SCSI_PR_CAP_EX_AC_AR) ?
+   BLK_PR_CAP_EX_AC_AR : 0;
+return res;
+}
+
+uint16_t block_pr_cap_to_scsi(uint8_t block_pr_cap)
+{
+uint16_t res = 0;
+res |= (block_pr_cap & BLK_PR_CAP_WR_EX) ?
+  SCSI_PR_CAP_WR_EX : 0;
+res |= (block_pr_cap & BLK_PR_CAP_EX_AC) ?
+  SCSI_PR_CAP_EX_AC : 0;
+res |= (block_pr_cap & BLK_PR_CAP_WR_EX_RO) ?
+  SCSI_PR_CAP_WR_EX_RO : 0;
+res |= (block_pr_cap & BLK_PR_CAP_EX_AC_RO) ?
+  SCSI_PR_CAP_EX_AC_RO : 0;
+res |= (block_pr_cap & BLK_PR_CAP_WR_EX_AR) ?
+  SCSI_PR_CAP_WR_EX_AR : 0;
+res |= (block_pr_cap & BLK_PR_CAP_EX_AC_AR) ?
+  SCSI_PR_CAP_EX_AC_AR : 0;
+return res;
+}
-- 
2.20.1




[PATCH v2 09/11] hw/nvme: enable namespace rescap function

2024-05-12 Thread Changqi Lu
This commit enables the rescap function in the
namespace by detecting the supported reservation
function in the backend driver.

Signed-off-by: Changqi Lu 
Signed-off-by: zhenwei pi 
---
 hw/nvme/ns.c | 7 +++
 1 file changed, 7 insertions(+)

diff --git a/hw/nvme/ns.c b/hw/nvme/ns.c
index ea8db175db..68a18636fb 100644
--- a/hw/nvme/ns.c
+++ b/hw/nvme/ns.c
@@ -20,6 +20,7 @@
 #include "qemu/bitops.h"
 #include "sysemu/sysemu.h"
 #include "sysemu/block-backend.h"
+#include "block/block_int.h"
 
 #include "nvme.h"
 #include "trace.h"
@@ -55,6 +56,12 @@ void nvme_ns_init_format(NvmeNamespace *ns)
 }
 
 id_ns->npda = id_ns->npdg = npdg - 1;
+
+/* The persistent reservation capacities of block
+ * and nvme are currently defined the same.
+ * If there are subsequent changes, this part needs to be changed.
+ */
+id_ns->rescap = blk_bs(ns->blkconf.blk)->file->bs->bl.pr_cap;
 }
 
 static int nvme_ns_init(NvmeNamespace *ns, Error **errp)
-- 
2.20.1




[PATCH v2 01/11] block: add persistent reservation in/out api

2024-05-12 Thread Changqi Lu
Add persistent reservation in/out operations
at the block level. The following operations
are included:

- read_keys:retrieves the list of registered keys.
- read_reservation: retrieves the current reservation status.
- register: registers a new reservation key.
- reserve:  initiates a reservation for a specific key.
- release:  releases a reservation for a specific key.
- clear:clears all existing reservations.
- preempt:  preempts a reservation held by another key.

Signed-off-by: Changqi Lu 
Signed-off-by: zhenwei pi 
---
 block/block-backend.c | 390 ++
 block/io.c| 161 
 include/block/block-common.h  |  40 +++
 include/block/block-io.h  |  19 ++
 include/block/block_int-common.h  |  85 +++
 include/sysemu/block-backend-io.h |  22 ++
 6 files changed, 717 insertions(+)

diff --git a/block/block-backend.c b/block/block-backend.c
index db6f9b92a3..b0030b312d 100644
--- a/block/block-backend.c
+++ b/block/block-backend.c
@@ -1770,6 +1770,396 @@ BlockAIOCB *blk_aio_ioctl(BlockBackend *blk, unsigned 
long int req, void *buf,
 return blk_aio_prwv(blk, req, 0, buf, blk_aio_ioctl_entry, 0, cb, opaque);
 }
 
+typedef struct BlkPrInCo {
+BlockBackend *blk;
+uint32_t *generation;
+uint32_t num_keys;
+BlockPrType *type;
+uint64_t *keys;
+int ret;
+} BlkPrInCo;
+
+typedef struct BlkPrInCB {
+BlockAIOCB common;
+BlkPrInCo prco;
+bool has_returned;
+} BlkPrInCB;
+
+static const AIOCBInfo blk_pr_in_aiocb_info = {
+.aiocb_size = sizeof(BlkPrInCB),
+};
+
+static void blk_pr_in_complete(BlkPrInCB *acb)
+{
+if (acb->has_returned) {
+acb->common.cb(acb->common.opaque, acb->prco.ret);
+blk_dec_in_flight(acb->prco.blk);
+qemu_aio_unref(acb);
+}
+}
+
+static void blk_pr_in_complete_bh(void *opaque)
+{
+BlkPrInCB *acb = opaque;
+assert(acb->has_returned);
+blk_pr_in_complete(acb);
+}
+
+static BlockAIOCB *blk_aio_pr_in(BlockBackend *blk, uint32_t *generation,
+ uint32_t num_keys, BlockPrType *type,
+ uint64_t *keys, CoroutineEntry co_entry,
+ BlockCompletionFunc *cb, void *opaque)
+{
+BlkPrInCB *acb;
+Coroutine *co;
+
+blk_inc_in_flight(blk);
+acb = blk_aio_get(_pr_in_aiocb_info, blk, cb, opaque);
+acb->prco = (BlkPrInCo) {
+.blk= blk,
+.generation = generation,
+.num_keys   = num_keys,
+.type   = type,
+.ret= NOT_DONE,
+.keys   = keys,
+};
+acb->has_returned = false;
+
+co = qemu_coroutine_create(co_entry, acb);
+aio_co_enter(qemu_get_current_aio_context(), co);
+
+acb->has_returned = true;
+if (acb->prco.ret != NOT_DONE) {
+replay_bh_schedule_oneshot_event(qemu_get_current_aio_context(),
+ blk_pr_in_complete_bh, acb);
+}
+
+return >common;
+}
+
+/* To be called between exactly one pair of blk_inc/dec_in_flight() */
+static int coroutine_fn
+blk_aio_pr_do_read_keys(BlockBackend *blk, uint32_t *generation,
+uint32_t num_keys, uint64_t *keys)
+{
+IO_CODE();
+
+blk_wait_while_drained(blk);
+GRAPH_RDLOCK_GUARD();
+
+if (!blk_co_is_available(blk)) {
+return -ENOMEDIUM;
+}
+
+return bdrv_co_pr_read_keys(blk_bs(blk), generation, num_keys, keys);
+}
+
+static void coroutine_fn blk_aio_pr_read_keys_entry(void *opaque)
+{
+BlkPrInCB *acb = opaque;
+BlkPrInCo *prco = >prco;
+
+prco->ret = blk_aio_pr_do_read_keys(prco->blk, prco->generation,
+prco->num_keys, prco->keys);
+blk_pr_in_complete(acb);
+}
+
+BlockAIOCB *blk_aio_pr_read_keys(BlockBackend *blk, uint32_t *generation,
+ uint32_t num_keys, uint64_t *keys,
+ BlockCompletionFunc *cb, void *opaque)
+{
+IO_CODE();
+return blk_aio_pr_in(blk, generation, num_keys, NULL, keys,
+ blk_aio_pr_read_keys_entry, cb, opaque);
+}
+
+/* To be called between exactly one pair of blk_inc/dec_in_flight() */
+static int coroutine_fn
+blk_aio_pr_do_read_reservation(BlockBackend *blk, uint32_t *generation,
+   uint64_t *key, BlockPrType *type)
+{
+IO_CODE();
+
+blk_wait_while_drained(blk);
+GRAPH_RDLOCK_GUARD();
+
+if (!blk_co_is_available(blk)) {
+return -ENOMEDIUM;
+}
+
+return bdrv_co_pr_read_reservation(blk_bs(blk), generation, key, type);
+}
+
+static void coroutine_fn blk_aio_pr_read_reservation_entry(void *opaque)
+{
+BlkPrInCB *acb = opaque;
+BlkPrInCo *prco = >prco;
+
+prco->ret = blk_aio_pr_do_read_reservation(prco->blk, prco->generation,
+   prco->keys, prco->type);
+

[PATCH v2 08/11] hw/nvme: enable ONCS reservations

2024-05-12 Thread Changqi Lu
This commit enables ONCS to support the reservation
function at the controller level. It also lays the
groundwork for detecting and enabling the reservation
function on a per-namespace basis in RESCAP.

Signed-off-by: Changqi Lu 
Signed-off-by: zhenwei pi 
---
 hw/nvme/ctrl.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/hw/nvme/ctrl.c b/hw/nvme/ctrl.c
index 127c3d2383..182307a48b 100644
--- a/hw/nvme/ctrl.c
+++ b/hw/nvme/ctrl.c
@@ -8248,7 +8248,8 @@ static void nvme_init_ctrl(NvmeCtrl *n, PCIDevice 
*pci_dev)
 id->nn = cpu_to_le32(NVME_MAX_NAMESPACES);
 id->oncs = cpu_to_le16(NVME_ONCS_WRITE_ZEROES | NVME_ONCS_TIMESTAMP |
NVME_ONCS_FEATURES | NVME_ONCS_DSM |
-   NVME_ONCS_COMPARE | NVME_ONCS_COPY);
+   NVME_ONCS_COMPARE | NVME_ONCS_COPY |
+   NVME_ONCS_RESRVATIONS);
 
 /*
  * NOTE: If this device ever supports a command set that does NOT use 0x0
-- 
2.20.1




[PATCH v2 10/11] hw/nvme: add reservation protocal command

2024-05-12 Thread Changqi Lu
Add reservation acquire, reservation register,
reservation release and reservation report commands
in the nvme device layer.

By introducing these commands, this enables the nvme
device to perform reservation-related tasks, including
querying keys, querying reservation status, registering
reservation keys, initiating and releasing reservations,
as well as clearing and preempting reservations held by
other keys.

These commands are crucial for management and control of
shared storage resources in a persistent manner.

Signed-off-by: Changqi Lu 
Signed-off-by: zhenwei pi 
---
 hw/nvme/ctrl.c   | 304 ++-
 hw/nvme/nvme.h   |   4 +
 include/block/nvme.h |  37 ++
 3 files changed, 344 insertions(+), 1 deletion(-)

diff --git a/hw/nvme/ctrl.c b/hw/nvme/ctrl.c
index 182307a48b..98a9a25647 100644
--- a/hw/nvme/ctrl.c
+++ b/hw/nvme/ctrl.c
@@ -294,6 +294,10 @@ static const uint32_t nvme_cse_iocs_nvm[256] = {
 [NVME_CMD_COMPARE]  = NVME_CMD_EFF_CSUPP,
 [NVME_CMD_IO_MGMT_RECV] = NVME_CMD_EFF_CSUPP,
 [NVME_CMD_IO_MGMT_SEND] = NVME_CMD_EFF_CSUPP | NVME_CMD_EFF_LBCC,
+[NVME_CMD_RESV_REGISTER]= NVME_CMD_EFF_CSUPP,
+[NVME_CMD_RESV_REPORT]  = NVME_CMD_EFF_CSUPP,
+[NVME_CMD_RESV_ACQUIRE] = NVME_CMD_EFF_CSUPP,
+[NVME_CMD_RESV_RELEASE] = NVME_CMD_EFF_CSUPP,
 };
 
 static const uint32_t nvme_cse_iocs_zoned[256] = {
@@ -308,6 +312,10 @@ static const uint32_t nvme_cse_iocs_zoned[256] = {
 [NVME_CMD_ZONE_APPEND]  = NVME_CMD_EFF_CSUPP | NVME_CMD_EFF_LBCC,
 [NVME_CMD_ZONE_MGMT_SEND]   = NVME_CMD_EFF_CSUPP | NVME_CMD_EFF_LBCC,
 [NVME_CMD_ZONE_MGMT_RECV]   = NVME_CMD_EFF_CSUPP,
+[NVME_CMD_RESV_REGISTER]= NVME_CMD_EFF_CSUPP,
+[NVME_CMD_RESV_REPORT]  = NVME_CMD_EFF_CSUPP,
+[NVME_CMD_RESV_ACQUIRE] = NVME_CMD_EFF_CSUPP,
+[NVME_CMD_RESV_RELEASE] = NVME_CMD_EFF_CSUPP,
 };
 
 static void nvme_process_sq(void *opaque);
@@ -1745,6 +1753,7 @@ static void nvme_aio_err(NvmeRequest *req, int ret)
 
 switch (req->cmd.opcode) {
 case NVME_CMD_READ:
+case NVME_CMD_RESV_REPORT:
 status = NVME_UNRECOVERED_READ;
 break;
 case NVME_CMD_FLUSH:
@@ -1752,6 +1761,9 @@ static void nvme_aio_err(NvmeRequest *req, int ret)
 case NVME_CMD_WRITE_ZEROES:
 case NVME_CMD_ZONE_APPEND:
 case NVME_CMD_COPY:
+case NVME_CMD_RESV_REGISTER:
+case NVME_CMD_RESV_ACQUIRE:
+case NVME_CMD_RESV_RELEASE:
 status = NVME_WRITE_FAULT;
 break;
 default:
@@ -2127,7 +2139,10 @@ static inline bool nvme_is_write(NvmeRequest *req)
 
 return rw->opcode == NVME_CMD_WRITE ||
rw->opcode == NVME_CMD_ZONE_APPEND ||
-   rw->opcode == NVME_CMD_WRITE_ZEROES;
+   rw->opcode == NVME_CMD_WRITE_ZEROES ||
+   rw->opcode == NVME_CMD_RESV_REGISTER ||
+   rw->opcode == NVME_CMD_RESV_ACQUIRE ||
+   rw->opcode == NVME_CMD_RESV_RELEASE;
 }
 
 static void nvme_misc_cb(void *opaque, int ret)
@@ -2692,6 +2707,285 @@ static uint16_t nvme_verify(NvmeCtrl *n, NvmeRequest 
*req)
 return NVME_NO_COMPLETE;
 }
 
+typedef struct NvmeKeyInfo {
+uint64_t cr_key;
+uint64_t nr_key;
+} NvmeKeyInfo;
+
+static uint16_t nvme_resv_register(NvmeCtrl *n, NvmeRequest *req)
+{
+int ret;
+NvmeKeyInfo key_info;
+NvmeNamespace *ns = req->ns;
+uint32_t cdw10 = le32_to_cpu(req->cmd.cdw10);
+bool ignore_key = cdw10 >> 3 & 0x1;
+uint8_t action = cdw10 & 0x7;
+
+ret = nvme_h2c(n, (uint8_t *)_info, sizeof(NvmeKeyInfo), req);
+if (ret) {
+return ret;
+}
+
+switch (action) {
+case NVME_RESV_REGISTER_ACTION_REGISTER:
+req->aiocb = blk_aio_pr_register(ns->blkconf.blk, 0,
+ key_info.nr_key, 0,
+ ignore_key, nvme_misc_cb,
+ req);
+break;
+case NVME_RESV_REGISTER_ACTION_UNREGISTER:
+req->aiocb = blk_aio_pr_register(ns->blkconf.blk, key_info.cr_key, 0,
+0, ignore_key, nvme_misc_cb, req);
+break;
+case NVME_RESV_REGISTER_ACTION_REPLACE:
+req->aiocb = blk_aio_pr_register(ns->blkconf.blk, key_info.cr_key,
+ key_info.nr_key, 0, ignore_key,
+ nvme_misc_cb, req);
+break;
+default:
+return NVME_INVALID_FIELD;
+}
+
+return NVME_NO_COMPLETE;
+}
+
+static uint16_t nvme_resv_release(NvmeCtrl *n, NvmeRequest *req)
+{
+int ret;
+uint64_t cr_key;
+NvmeNamespace *ns = req->ns;
+uint32_t cdw10 = le32_to_cpu(req->cmd.cdw10);
+uint8_t action = cdw10 & 0x7;
+NVMEResvType type = cdw10 >> 8 & 0xff;
+
+ret = nvme_h2c(n, (uint8_t *)_key, sizeof(cr_key), req);
+if (ret) {
+return ret;
+}
+
+

[PATCH v2 11/11] block/iscsi: add persistent reservation in/out driver

2024-05-12 Thread Changqi Lu
Add persistent reservation in/out operations for iscsi driver.
The following methods are implemented: bdrv_co_pr_read_keys,
bdrv_co_pr_read_reservation, bdrv_co_pr_register, bdrv_co_pr_reserve,
bdrv_co_pr_release, bdrv_co_pr_clear and bdrv_co_pr_preempt.

Signed-off-by: Changqi Lu 
Signed-off-by: zhenwei pi 
---
 block/iscsi.c | 448 ++
 1 file changed, 448 insertions(+)

diff --git a/block/iscsi.c b/block/iscsi.c
index 2ff14b7472..5791fd36e0 100644
--- a/block/iscsi.c
+++ b/block/iscsi.c
@@ -96,6 +96,7 @@ typedef struct IscsiLun {
 unsigned long *allocmap_valid;
 long allocmap_size;
 int cluster_size;
+uint8_t pr_cap;
 bool use_16_for_rw;
 bool write_protected;
 bool lbpme;
@@ -280,6 +281,8 @@ iscsi_co_generic_cb(struct iscsi_context *iscsi, int status,
 iTask->err_code = -error;
 iTask->err_str = g_strdup(iscsi_get_error(iscsi));
 }
+} else if (status == SCSI_STATUS_RESERVATION_CONFLICT) {
+iTask->err_code = -EBADE;
 }
 }
 }
@@ -1792,6 +1795,53 @@ static void iscsi_save_designator(IscsiLun *lun,
 }
 }
 
+static void iscsi_get_pr_cap_sync(IscsiLun *iscsilun, Error **errp)
+{
+struct scsi_task *task = NULL;
+struct scsi_persistent_reserve_in_report_capabilities *rc = NULL;
+int retries = ISCSI_CMD_RETRIES;
+int xferlen = sizeof(struct 
scsi_persistent_reserve_in_report_capabilities);
+
+do {
+if (task != NULL) {
+scsi_free_scsi_task(task);
+task = NULL;
+}
+
+task = iscsi_persistent_reserve_in_sync(iscsilun->iscsi,
+   iscsilun->lun, SCSI_PR_IN_REPORT_CAPABILITIES, xferlen);
+if (task != NULL && task->status == SCSI_STATUS_GOOD) {
+rc = scsi_datain_unmarshall(task);
+if (rc == NULL) {
+error_setg(errp,
+"iSCSI: Failed to unmarshall report capabilities data.");
+} else {
+iscsilun->pr_cap =
+scsi_pr_cap_to_block(rc->persistent_reservation_type_mask);
+/* aptpl is enable by default. */
+iscsilun->pr_cap |= 1;
+}
+break;
+}
+
+if (task != NULL && task->status == SCSI_STATUS_CHECK_CONDITION
+&& task->sense.key == SCSI_SENSE_UNIT_ATTENTION) {
+break;
+}
+
+} while (task != NULL && task->status == SCSI_STATUS_CHECK_CONDITION
+ && task->sense.key == SCSI_SENSE_UNIT_ATTENTION
+ && retries-- > 0);
+
+if (task == NULL || task->status != SCSI_STATUS_GOOD) {
+error_setg(errp, "iSCSI: failed to send report capabilities command");
+}
+
+if (task) {
+scsi_free_scsi_task(task);
+}
+}
+
 static int iscsi_open(BlockDriverState *bs, QDict *options, int flags,
   Error **errp)
 {
@@ -2024,6 +2074,11 @@ static int iscsi_open(BlockDriverState *bs, QDict 
*options, int flags,
 bs->supported_zero_flags = BDRV_REQ_MAY_UNMAP;
 }
 
+iscsi_get_pr_cap_sync(iscsilun, _err);
+if (local_err != NULL) {
+error_propagate(errp, local_err);
+ret = -EINVAL;
+}
 out:
 qemu_opts_del(opts);
 g_free(initiator_name);
@@ -2110,6 +2165,8 @@ static void iscsi_refresh_limits(BlockDriverState *bs, 
Error **errp)
 bs->bl.opt_transfer = pow2floor(iscsilun->bl.opt_xfer_len *
 iscsilun->block_size);
 }
+
+bs->bl.pr_cap = iscsilun->pr_cap;
 }
 
 /* Note that this will not re-establish a connection with an iSCSI target - it
@@ -2408,6 +2465,389 @@ out_unlock:
 return r;
 }
 
+static int coroutine_fn
+iscsi_co_pr_read_keys(BlockDriverState *bs, uint32_t *generation,
+  uint32_t num_keys, uint64_t *keys)
+{
+IscsiLun *iscsilun = bs->opaque;
+QEMUIOVector qiov;
+struct IscsiTask iTask;
+int xferlen = sizeof(struct scsi_persistent_reserve_in_read_keys) +
+  sizeof(uint64_t) * num_keys;
+uint8_t *buf = g_malloc0(xferlen);
+int32_t num_collect_keys = 0;
+int r = 0;
+
+qemu_iovec_init_buf(, buf, xferlen);
+iscsi_co_init_iscsitask(iscsilun, );
+qemu_mutex_lock(>mutex);
+retry:
+iTask.task = iscsi_persistent_reserve_in_task(iscsilun->iscsi,
+ iscsilun->lun, SCSI_PR_IN_READ_KEYS, xferlen,
+ iscsi_co_generic_cb, );
+
+if (iTask.task == NULL) {
+qemu_mutex_unlock(>mutex);
+return -ENOMEM;
+}
+
+scsi_task_set_iov_in(iTask.task, (struct scsi_iovec *)qiov.iov, qiov.niov);
+iscsi_co_wait_for_task(, iscsilun);
+
+if (iTask.task != NULL) {
+scsi_free_scsi_task(iTask.task);
+iTask.task = NULL;
+}
+
+if (iTask.do_retry) {
+iTask.complete = 0;
+goto retry;
+}
+
+if (iTask.status != 

[PATCH v2 05/11] hw/scsi: add persistent reservation in/out api for scsi device

2024-05-12 Thread Changqi Lu
Add persistent reservation in/out operations in the
SCSI device layer. By introducing the persistent
reservation in/out api, this enables the SCSI device
to perform reservation-related tasks, including querying
keys, querying reservation status, registering reservation
keys, initiating and releasing reservations, as well as
clearing and preempting reservations held by other keys.

These operations are crucial for management and control of
shared storage resources in a persistent manner.

Signed-off-by: Changqi Lu 
Signed-off-by: zhenwei pi 
---
 hw/scsi/scsi-disk.c | 348 
 1 file changed, 348 insertions(+)

diff --git a/hw/scsi/scsi-disk.c b/hw/scsi/scsi-disk.c
index 4bd7af9d0c..0c7c1b4f72 100644
--- a/hw/scsi/scsi-disk.c
+++ b/hw/scsi/scsi-disk.c
@@ -32,6 +32,7 @@
 #include "migration/vmstate.h"
 #include "hw/scsi/emulation.h"
 #include "scsi/constants.h"
+#include "scsi/utils.h"
 #include "sysemu/block-backend.h"
 #include "sysemu/blockdev.h"
 #include "hw/block/block.h"
@@ -42,6 +43,7 @@
 #include "qemu/cutils.h"
 #include "trace.h"
 #include "qom/object.h"
+#include "block/block_int.h"
 
 #ifdef __linux
 #include 
@@ -1474,6 +1476,342 @@ static void scsi_disk_emulate_read_data(SCSIRequest 
*req)
 scsi_req_complete(>req, GOOD);
 }
 
+typedef struct SCSIPrReadKeys {
+uint32_t generation;
+uint32_t num_keys;
+uint64_t *keys;
+void *req;
+} SCSIPrReadKeys;
+
+typedef struct SCSIPrReadReservation {
+uint32_t generation;
+uint64_t key;
+BlockPrType type;
+void *req;
+} SCSIPrReadReservation;
+
+static void scsi_pr_read_keys_complete(void *opaque, int ret)
+{
+int num_keys;
+uint8_t *buf;
+SCSIPrReadKeys *blk_keys = (SCSIPrReadKeys *)opaque;
+SCSIDiskReq *r = (SCSIDiskReq *)blk_keys->req;
+SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
+
+assert(blk_get_aio_context(s->qdev.conf.blk) ==
+qemu_get_current_aio_context());
+
+assert(r->req.aiocb != NULL);
+r->req.aiocb = NULL;
+
+if (scsi_disk_req_check_error(r, ret, true)) {
+goto done;
+}
+
+buf = scsi_req_get_buf(>req);
+num_keys = MIN(blk_keys->num_keys, ret);
+blk_keys->generation = cpu_to_be32(blk_keys->generation);
+memcpy([0], _keys->generation, 4);
+for (int i = 0; i < num_keys; i++) {
+blk_keys->keys[i] = cpu_to_be64(blk_keys->keys[i]);
+memcpy([8 + i * 8], _keys->keys[i], 8);
+}
+num_keys = cpu_to_be32(num_keys * 8);
+memcpy([4], _keys, 4);
+
+scsi_req_data(>req, r->buflen);
+done:
+scsi_req_unref(>req);
+g_free(blk_keys->keys);
+g_free(blk_keys);
+}
+
+static int scsi_disk_emulate_pr_read_keys(SCSIRequest *req)
+{
+SCSIPrReadKeys *blk_keys;
+SCSIDiskReq *r = DO_UPCAST(SCSIDiskReq, req, req);
+SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, req->dev);
+int buflen = MIN(r->req.cmd.xfer, r->buflen);
+int num_keys = (buflen - sizeof(uint32_t) * 2) / sizeof(uint64_t);
+
+blk_keys = g_new0(SCSIPrReadKeys, 1);
+blk_keys->generation = 0;
+/* num_keys is the maximum number of keys that can be transmitted */
+blk_keys->num_keys = num_keys;
+blk_keys->keys = g_malloc(sizeof(uint64_t) * num_keys);
+blk_keys->req = r;
+
+/* The request is used as the AIO opaque value, so add a ref.  */
+scsi_req_ref(>req);
+r->req.aiocb = blk_aio_pr_read_keys(s->qdev.conf.blk, 
_keys->generation,
+blk_keys->num_keys, blk_keys->keys,
+scsi_pr_read_keys_complete, blk_keys);
+return 0;
+}
+
+static void scsi_pr_read_reservation_complete(void *opaque, int ret)
+{
+uint8_t *buf;
+uint32_t additional_len = 0;
+SCSIPrReadReservation *blk_rsv = (SCSIPrReadReservation *)opaque;
+SCSIDiskReq *r = (SCSIDiskReq *)blk_rsv->req;
+SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
+
+assert(blk_get_aio_context(s->qdev.conf.blk) ==
+qemu_get_current_aio_context());
+
+assert(r->req.aiocb != NULL);
+r->req.aiocb = NULL;
+
+if (scsi_disk_req_check_error(r, ret, true)) {
+goto done;
+}
+
+buf = scsi_req_get_buf(>req);
+blk_rsv->generation = cpu_to_be32(blk_rsv->generation);
+memcpy([0], _rsv->generation, 4);
+if (ret) {
+additional_len = cpu_to_be32(16);
+blk_rsv->key = cpu_to_be64(blk_rsv->key);
+memcpy([8], _rsv->key, 8);
+buf[21] = block_pr_type_to_scsi(blk_rsv->type) & 0xf;
+} else {
+additional_len = cpu_to_be32(0);
+}
+
+memcpy([4], _len, 4);
+scsi_req_data(>req, r->buflen);
+
+done:
+scsi_req_unref(>req);
+g_free(blk_rsv);
+}
+
+static int scsi_disk_emulate_pr_read_reservation(SCSIRequest *req)
+{
+SCSIPrReadReservation *blk_rsv;
+SCSIDiskReq *r = DO_UPCAST(SCSIDiskReq, req, req);
+SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, req->dev);
+
+blk_rsv = 

[PATCH v2 03/11] scsi/constant: add persistent reservation in/out protocol constants

2024-05-12 Thread Changqi Lu
Add constants for the persistent reservation in/out protocol
in the scsi/constant module. The constants include the persistent
reservation command, type, and scope values defined in sections
6.13 and 6.14 of the SCSI Primary Commands-4 (SPC-4) specification.

Signed-off-by: Changqi Lu 
Signed-off-by: zhenwei pi 
---
 include/scsi/constants.h | 52 
 1 file changed, 52 insertions(+)

diff --git a/include/scsi/constants.h b/include/scsi/constants.h
index 9b98451912..922a314535 100644
--- a/include/scsi/constants.h
+++ b/include/scsi/constants.h
@@ -319,4 +319,56 @@
 #define IDENT_DESCR_TGT_DESCR_SIZE 32
 #define XCOPY_BLK2BLK_SEG_DESC_SIZE 28
 
+typedef enum {
+SCSI_PR_WRITE_EXCLUSIVE = 0x01,
+SCSI_PR_EXCLUSIVE_ACCESS= 0x03,
+SCSI_PR_WRITE_EXCLUSIVE_REGS_ONLY   = 0x05,
+SCSI_PR_EXCLUSIVE_ACCESS_REGS_ONLY  = 0x06,
+SCSI_PR_WRITE_EXCLUSIVE_ALL_REGS= 0x07,
+SCSI_PR_EXCLUSIVE_ACCESS_ALL_REGS   = 0x08,
+} SCSIPrType;
+
+typedef enum {
+SCSI_PR_LU_SCOPE  = 0x00,
+} SCSIPrScope;
+
+typedef enum {
+SCSI_PR_OUT_REGISTER = 0x0,
+SCSI_PR_OUT_RESERVE  = 0x1,
+SCSI_PR_OUT_RELEASE  = 0x2,
+SCSI_PR_OUT_CLEAR= 0x3,
+SCSI_PR_OUT_PREEMPT  = 0x4,
+SCSI_PR_OUT_PREEMPT_AND_ABORT= 0x5,
+SCSI_PR_OUT_REG_AND_IGNORE_KEY   = 0x6,
+SCSI_PR_OUT_REG_AND_MOVE = 0x7,
+} SCSIPrOutAction;
+
+typedef enum {
+SCSI_PR_IN_READ_KEYS = 0x0,
+SCSI_PR_IN_READ_RESERVATION  = 0x1,
+SCSI_PR_IN_REPORT_CAPABILITIES   = 0x2,
+} SCSIPrInAction;
+
+typedef enum {
+/* Exclusive Access All Registrants reservation type */
+SCSI_PR_CAP_EX_AC_AR = 1 << 0,
+/* Write Exclusive reservation type */
+SCSI_PR_CAP_WR_EX = 1 << 9,
+/* Exclusive Access reservation type */
+SCSI_PR_CAP_EX_AC = 1 << 11,
+/* Write Exclusive Registrants Only reservation type */
+SCSI_PR_CAP_WR_EX_RO = 1 << 13,
+/* Exclusive Access Registrants Only reservation type */
+SCSI_PR_CAP_EX_AC_RO = 1 << 14,
+/* Write Exclusive All Registrants reservation type */
+SCSI_PR_CAP_WR_EX_AR = 1 << 15,
+
+SCSI_PR_CAP_ALL = (SCSI_PR_CAP_EX_AC_AR |
+  SCSI_PR_CAP_WR_EX |
+  SCSI_PR_CAP_EX_AC |
+  SCSI_PR_CAP_WR_EX_RO |
+  SCSI_PR_CAP_EX_AC_RO |
+  SCSI_PR_CAP_WR_EX_AR),
+} SCSIPrCap;
+
 #endif
-- 
2.20.1




[PATCH v2 00/11] Support persistent reservation operations

2024-05-12 Thread Changqi Lu
Hi Stefan;

Thanks for your advices! The existing PRManager only works with
local scsi devices. This series will completely decouple devices
and drivers. The device can not only be scsi, but also other
devices such as nvme. The same is true for the driver,
which is completely unrestricted. And block/file-posix.c can
implement the new block driver, and pr_manager can be executed
after splicing ioctl commands in these drivers. This will be implemented
in subsequent patches.

v1->v2:
- Add sg_persist --report-capabilities for SCSI protocol and enable
  oncs and rescap for NVMe protocol.
- Add persistent reservation capabilities constants and helper functions for
  SCSI and NVMe protocol.
- Add comments for necessary APIs.
  
v1:
- Add seven APIs about persistent reservation command for block layer.
  These APIs including reading keys, reading reservations, registering,
  reserving, releasing, clearing and preempting.
- Add the necessary pr-related operation APIs for both the
  SCSI protocol and NVMe protocol at the device layer.
- Add scsi driver at the driver layer to verify the functions.

Changqi Lu (11):
  block: add persistent reservation in/out api
  block/raw: add persistent reservation in/out driver
  scsi/constant: add persistent reservation in/out protocol constants
  scsi/util: add helper functions for persistent reservation types
conversion
  hw/scsi: add persistent reservation in/out api for scsi device
  block/nvme: add reservation command protocol constants
  hw/nvme: add helper functions for converting reservation types
  hw/nvme: enable ONCS reservations
  hw/nvme: enable namespace rescap function
  hw/nvme: add reservation protocal command
  block/iscsi: add persistent reservation in/out driver

 block/block-backend.c | 390 ++
 block/io.c| 161 +++
 block/iscsi.c | 448 ++
 block/raw-format.c|  55 
 hw/nvme/ctrl.c| 307 +++-
 hw/nvme/ns.c  |   7 +
 hw/nvme/nvme.h|  44 +++
 hw/scsi/scsi-disk.c   | 348 +++
 include/block/block-common.h  |  40 +++
 include/block/block-io.h  |  19 ++
 include/block/block_int-common.h  |  85 ++
 include/block/nvme.h  |  92 ++
 include/scsi/constants.h  |  52 
 include/scsi/utils.h  |   8 +
 include/sysemu/block-backend-io.h |  22 ++
 scsi/utils.c  |  77 +
 16 files changed, 2153 insertions(+), 2 deletions(-)

-- 
2.20.1




[PATCH v2 07/11] hw/nvme: add helper functions for converting reservation types

2024-05-12 Thread Changqi Lu
This commit introduces two helper functions
that facilitate the conversion between the
reservation types used in the NVME protocol
and those used in the block layer.

Reviewed-by: Stefan Hajnoczi 
Signed-off-by: Changqi Lu 
Signed-off-by: zhenwei pi 
---
 hw/nvme/nvme.h | 40 
 1 file changed, 40 insertions(+)

diff --git a/hw/nvme/nvme.h b/hw/nvme/nvme.h
index bed8191bd5..6abe479410 100644
--- a/hw/nvme/nvme.h
+++ b/hw/nvme/nvme.h
@@ -474,6 +474,46 @@ static inline const char *nvme_io_opc_str(uint8_t opc)
 }
 }
 
+static inline NVMEResvType block_pr_type_to_nvme(BlockPrType type)
+{
+switch (type) {
+case BLK_PR_WRITE_EXCLUSIVE:
+return NVME_RESV_WRITE_EXCLUSIVE;
+case BLK_PR_EXCLUSIVE_ACCESS:
+return NVME_RESV_EXCLUSIVE_ACCESS;
+case BLK_PR_WRITE_EXCLUSIVE_REGS_ONLY:
+return NVME_RESV_WRITE_EXCLUSIVE_REGS_ONLY;
+case BLK_PR_EXCLUSIVE_ACCESS_REGS_ONLY:
+return NVME_RESV_EXCLUSIVE_ACCESS_REGS_ONLY;
+case BLK_PR_WRITE_EXCLUSIVE_ALL_REGS:
+return NVME_RESV_WRITE_EXCLUSIVE_ALL_REGS;
+case BLK_PR_EXCLUSIVE_ACCESS_ALL_REGS:
+return NVME_RESV_EXCLUSIVE_ACCESS_ALL_REGS;
+}
+
+return 0;
+}
+
+static inline BlockPrType nvme_pr_type_to_block(NVMEResvType type)
+{
+switch (type) {
+case NVME_RESV_WRITE_EXCLUSIVE:
+return BLK_PR_WRITE_EXCLUSIVE;
+case NVME_RESV_EXCLUSIVE_ACCESS:
+return BLK_PR_EXCLUSIVE_ACCESS;
+case NVME_RESV_WRITE_EXCLUSIVE_REGS_ONLY:
+return BLK_PR_WRITE_EXCLUSIVE_REGS_ONLY;
+case NVME_RESV_EXCLUSIVE_ACCESS_REGS_ONLY:
+return BLK_PR_EXCLUSIVE_ACCESS_REGS_ONLY;
+case NVME_RESV_WRITE_EXCLUSIVE_ALL_REGS:
+return BLK_PR_WRITE_EXCLUSIVE_ALL_REGS;
+case NVME_RESV_EXCLUSIVE_ACCESS_ALL_REGS:
+return BLK_PR_EXCLUSIVE_ACCESS_ALL_REGS;
+}
+
+return 0;
+}
+
 typedef struct NvmeSQueue {
 struct NvmeCtrl *ctrl;
 uint16_tsqid;
-- 
2.20.1




[PATCH v2 02/11] block/raw: add persistent reservation in/out driver

2024-05-12 Thread Changqi Lu
Add persistent reservation in/out operations for raw driver.
The following methods are implemented: bdrv_co_pr_read_keys,
bdrv_co_pr_read_reservation, bdrv_co_pr_register, bdrv_co_pr_reserve,
bdrv_co_pr_release, bdrv_co_pr_clear and bdrv_co_pr_preempt.

Reviewed-by: Stefan Hajnoczi 
Signed-off-by: Changqi Lu 
Signed-off-by: zhenwei pi 
---
 block/raw-format.c | 55 ++
 1 file changed, 55 insertions(+)

diff --git a/block/raw-format.c b/block/raw-format.c
index ac7e8495f6..7ba5b12101 100644
--- a/block/raw-format.c
+++ b/block/raw-format.c
@@ -454,6 +454,54 @@ raw_co_ioctl(BlockDriverState *bs, unsigned long int req, 
void *buf)
 return bdrv_co_ioctl(bs->file->bs, req, buf);
 }
 
+static int coroutine_fn GRAPH_RDLOCK
+raw_co_pr_read_keys(BlockDriverState *bs, uint32_t *generation,
+uint32_t num_keys, uint64_t *keys)
+{
+
+return bdrv_co_pr_read_keys(bs->file->bs, generation, num_keys, keys);
+}
+
+static int coroutine_fn GRAPH_RDLOCK
+raw_co_pr_read_reservation(BlockDriverState *bs, uint32_t *generation,
+   uint64_t *key, BlockPrType *type)
+{
+return bdrv_co_pr_read_reservation(bs->file->bs, generation, key, type);
+}
+
+static int coroutine_fn GRAPH_RDLOCK
+raw_co_pr_register(BlockDriverState *bs, uint64_t old_key,
+   uint64_t new_key, BlockPrType type, bool ignore_key)
+{
+return bdrv_co_pr_register(bs->file->bs, old_key, new_key,
+   type, ignore_key);
+}
+
+static int coroutine_fn GRAPH_RDLOCK
+raw_co_pr_reserve(BlockDriverState *bs, uint64_t key, BlockPrType type)
+{
+return bdrv_co_pr_reserve(bs->file->bs, key, type);
+}
+
+static int coroutine_fn GRAPH_RDLOCK
+raw_co_pr_release(BlockDriverState *bs, uint64_t key, BlockPrType type)
+{
+return bdrv_co_pr_release(bs->file->bs, key, type);
+}
+
+static int coroutine_fn GRAPH_RDLOCK
+raw_co_pr_clear(BlockDriverState *bs, uint64_t key)
+{
+return bdrv_co_pr_clear(bs->file->bs, key);
+}
+
+static int coroutine_fn GRAPH_RDLOCK
+raw_co_pr_preempt(BlockDriverState *bs, uint64_t old_key,
+  uint64_t new_key, BlockPrType type, bool abort)
+{
+return bdrv_co_pr_preempt(bs->file->bs, old_key, new_key, type, abort);
+}
+
 static int GRAPH_RDLOCK raw_has_zero_init(BlockDriverState *bs)
 {
 return bdrv_has_zero_init(bs->file->bs);
@@ -672,6 +720,13 @@ BlockDriver bdrv_raw = {
 .strong_runtime_opts  = raw_strong_runtime_opts,
 .mutable_opts = mutable_opts,
 .bdrv_cancel_in_flight = raw_cancel_in_flight,
+.bdrv_co_pr_read_keys= raw_co_pr_read_keys,
+.bdrv_co_pr_read_reservation = raw_co_pr_read_reservation,
+.bdrv_co_pr_register = raw_co_pr_register,
+.bdrv_co_pr_reserve  = raw_co_pr_reserve,
+.bdrv_co_pr_release  = raw_co_pr_release,
+.bdrv_co_pr_clear= raw_co_pr_clear,
+.bdrv_co_pr_preempt  = raw_co_pr_preempt,
 };
 
 static void bdrv_raw_init(void)
-- 
2.20.1




Re: [PATCH RESEND] target/riscv/cpu.c: fix Zvkb extension config

2024-05-12 Thread Alistair Francis
On Sat, May 11, 2024 at 9:28 PM Yangyu Chen  wrote:
>
> This code has a typo that writes zvkb to zvkg, causing users can't
> enable zvkb through the config. This patch gets this fixed.
>
> Signed-off-by: Yangyu Chen 
> Fixes: ea61ef7097d0 ("target/riscv: Move vector crypto extensions to 
> riscv_cpu_extensions")
> Reviewed-by: LIU Zhiwei 

Thanks!

Applied to riscv-to-apply.next

Alistair

> ---
>  target/riscv/cpu.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
> index eb1a2e7d6d..13cd34adbd 100644
> --- a/target/riscv/cpu.c
> +++ b/target/riscv/cpu.c
> @@ -1535,7 +1535,7 @@ const RISCVCPUMultiExtConfig riscv_cpu_extensions[] = {
>  /* Vector cryptography extensions */
>  MULTI_EXT_CFG_BOOL("zvbb", ext_zvbb, false),
>  MULTI_EXT_CFG_BOOL("zvbc", ext_zvbc, false),
> -MULTI_EXT_CFG_BOOL("zvkb", ext_zvkg, false),
> +MULTI_EXT_CFG_BOOL("zvkb", ext_zvkb, false),
>  MULTI_EXT_CFG_BOOL("zvkg", ext_zvkg, false),
>  MULTI_EXT_CFG_BOOL("zvkned", ext_zvkned, false),
>  MULTI_EXT_CFG_BOOL("zvknha", ext_zvknha, false),
> --
> 2.43.0
>
>



Re: [PATCH RESEND] target/riscv/cpu.c: fix Zvkb extension config

2024-05-12 Thread Alistair Francis
On Sat, May 11, 2024 at 9:28 PM Yangyu Chen  wrote:
>
> This code has a typo that writes zvkb to zvkg, causing users can't
> enable zvkb through the config. This patch gets this fixed.
>
> Signed-off-by: Yangyu Chen 
> Fixes: ea61ef7097d0 ("target/riscv: Move vector crypto extensions to 
> riscv_cpu_extensions")
> Reviewed-by: LIU Zhiwei 

Reviewed-by: Alistair Francis 

Alistair

> ---
>  target/riscv/cpu.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
> index eb1a2e7d6d..13cd34adbd 100644
> --- a/target/riscv/cpu.c
> +++ b/target/riscv/cpu.c
> @@ -1535,7 +1535,7 @@ const RISCVCPUMultiExtConfig riscv_cpu_extensions[] = {
>  /* Vector cryptography extensions */
>  MULTI_EXT_CFG_BOOL("zvbb", ext_zvbb, false),
>  MULTI_EXT_CFG_BOOL("zvbc", ext_zvbc, false),
> -MULTI_EXT_CFG_BOOL("zvkb", ext_zvkg, false),
> +MULTI_EXT_CFG_BOOL("zvkb", ext_zvkb, false),
>  MULTI_EXT_CFG_BOOL("zvkg", ext_zvkg, false),
>  MULTI_EXT_CFG_BOOL("zvkned", ext_zvkned, false),
>  MULTI_EXT_CFG_BOOL("zvknha", ext_zvknha, false),
> --
> 2.43.0
>
>



Re: [PATCH 1/5] target/riscv: Reuse the conversion function of priv_spec and string

2024-05-12 Thread LIU Zhiwei



On 2024/5/10 14:58, Fea.Wang wrote:

From: Jim Shu 

Public the conversion function of priv_spec and string in cpu.h, so that
tcg-cpu.c could also use it.

Signed-off-by: Jim Shu 
Signed-off-by: Fea.Wang 
Reviewed-by: Frank Chang 
---
  target/riscv/cpu.c |  4 ++--
  target/riscv/cpu.h |  3 +++
  target/riscv/tcg/tcg-cpu.c | 13 +
  3 files changed, 10 insertions(+), 10 deletions(-)

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index a74f0eb29c..b6b48e5620 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -1769,7 +1769,7 @@ static const PropertyInfo prop_pmp = {
  .set = prop_pmp_set,
  };
  
-static int priv_spec_from_str(const char *priv_spec_str)

+int priv_spec_from_str(const char *priv_spec_str)
  {
  int priv_version = -1;
  
@@ -1784,7 +1784,7 @@ static int priv_spec_from_str(const char *priv_spec_str)

  return priv_version;
  }
  
-static const char *priv_spec_to_str(int priv_version)

+const char *priv_spec_to_str(int priv_version)
  {
  switch (priv_version) {
  case PRIV_VERSION_1_10_0:
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index e0dd1828b5..7696102697 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -829,4 +829,7 @@ target_ulong riscv_new_csr_seed(target_ulong new_value,
  uint8_t satp_mode_max_from_map(uint32_t map);
  const char *satp_mode_str(uint8_t satp_mode, bool is_32_bit);
  
+const char *priv_spec_to_str(int priv_version);

+int priv_spec_from_str(const char *priv_spec_str);
+
  #endif /* RISCV_CPU_H */
diff --git a/target/riscv/tcg/tcg-cpu.c b/target/riscv/tcg/tcg-cpu.c
index 4ebebebe09..faa8de9b83 100644
--- a/target/riscv/tcg/tcg-cpu.c
+++ b/target/riscv/tcg/tcg-cpu.c
@@ -76,16 +76,13 @@ static void riscv_cpu_write_misa_bit(RISCVCPU *cpu, 
uint32_t bit,
  
  static const char *cpu_priv_ver_to_str(int priv_ver)

  {
-switch (priv_ver) {
-case PRIV_VERSION_1_10_0:
-return "v1.10.0";
-case PRIV_VERSION_1_11_0:
-return "v1.11.0";
-case PRIV_VERSION_1_12_0:
-return "v1.12.0";
+const char *priv_spec_str = priv_spec_to_str(priv_ver);
+
+if (priv_spec_str == NULL) {
+g_assert_not_reached();
  }


g_assert(priv_spec_str != NULL) or g_assert(priv_spec_str)

Otherwise,

Reviewed-by: LIU Zhiwei 

Zhiwei

  
-g_assert_not_reached();

+return priv_spec_str;
  }
  
  static void riscv_cpu_synchronize_from_tb(CPUState *cs,




Re: [PATCH 2/5] target/riscv: Support the version for ss1p13

2024-05-12 Thread LIU Zhiwei



On 2024/5/10 14:58, Fea.Wang wrote:

Add RISC-V privilege 1.13 support.

Signed-off-by: Fea.Wang 
Reviewed-by: Frank Chang 


Reviewed-by: LIU Zhiwei 

Zhiwei


---
  target/riscv/cpu.c | 6 +-
  target/riscv/cpu.h | 4 +++-
  target/riscv/cpu_cfg.h | 1 +
  target/riscv/tcg/tcg-cpu.c | 4 
  4 files changed, 13 insertions(+), 2 deletions(-)

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index b6b48e5620..a6298c3298 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -1773,7 +1773,9 @@ int priv_spec_from_str(const char *priv_spec_str)
  {
  int priv_version = -1;
  
-if (!g_strcmp0(priv_spec_str, PRIV_VER_1_12_0_STR)) {

+if (!g_strcmp0(priv_spec_str, PRIV_VER_1_13_0_STR)) {
+priv_version = PRIV_VERSION_1_13_0;
+} else if (!g_strcmp0(priv_spec_str, PRIV_VER_1_12_0_STR)) {
  priv_version = PRIV_VERSION_1_12_0;
  } else if (!g_strcmp0(priv_spec_str, PRIV_VER_1_11_0_STR)) {
  priv_version = PRIV_VERSION_1_11_0;
@@ -1793,6 +1795,8 @@ const char *priv_spec_to_str(int priv_version)
  return PRIV_VER_1_11_0_STR;
  case PRIV_VERSION_1_12_0:
  return PRIV_VER_1_12_0_STR;
+case PRIV_VERSION_1_13_0:
+return PRIV_VER_1_13_0_STR;
  default:
  return NULL;
  }
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index 7696102697..776939b56b 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -96,12 +96,14 @@ extern RISCVCPUProfile *riscv_profiles[];
  #define PRIV_VER_1_10_0_STR "v1.10.0"
  #define PRIV_VER_1_11_0_STR "v1.11.0"
  #define PRIV_VER_1_12_0_STR "v1.12.0"
+#define PRIV_VER_1_13_0_STR "v1.13.0"
  enum {
  PRIV_VERSION_1_10_0 = 0,
  PRIV_VERSION_1_11_0,
  PRIV_VERSION_1_12_0,
+PRIV_VERSION_1_13_0,
  
-PRIV_VERSION_LATEST = PRIV_VERSION_1_12_0,

+PRIV_VERSION_LATEST = PRIV_VERSION_1_13_0,
  };
  
  #define VEXT_VERSION_1_00_0 0x0001

diff --git a/target/riscv/cpu_cfg.h b/target/riscv/cpu_cfg.h
index e1e4f32698..fb7eebde52 100644
--- a/target/riscv/cpu_cfg.h
+++ b/target/riscv/cpu_cfg.h
@@ -136,6 +136,7 @@ struct RISCVCPUConfig {
   * TCG always implement/can't be user disabled,
   * based on spec version.
   */
+bool has_priv_1_13;
  bool has_priv_1_12;
  bool has_priv_1_11;
  
diff --git a/target/riscv/tcg/tcg-cpu.c b/target/riscv/tcg/tcg-cpu.c

index faa8de9b83..a9d188a9fd 100644
--- a/target/riscv/tcg/tcg-cpu.c
+++ b/target/riscv/tcg/tcg-cpu.c
@@ -320,6 +320,10 @@ static void riscv_cpu_update_named_features(RISCVCPU *cpu)
  cpu->cfg.has_priv_1_12 = true;
  }
  
+if (cpu->env.priv_ver >= PRIV_VERSION_1_13_0) {

+cpu->cfg.has_priv_1_13 = true;
+}
+
  /* zic64b is 1.12 or later */
  cpu->cfg.ext_zic64b = cpu->cfg.cbom_blocksize == 64 &&
cpu->cfg.cbop_blocksize == 64 &&




Re: [PATCH 3/5] target/riscv: Add 'P1P13' bit in SMSTATEEN0

2024-05-12 Thread LIU Zhiwei



On 2024/5/10 14:58, Fea.Wang wrote:

Based on privilege 1.13 spec, there should be a bit56 for 'P1P13' in
SMSTATEEN0 that controls access to the hedeleg.

Signed-off-by: Fea.Wang 
Reviewed-by: Frank Chang 
---
  target/riscv/cpu_bits.h |  1 +
  target/riscv/csr.c  | 10 ++
  2 files changed, 11 insertions(+)

diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h
index 74318a925c..28bd3fb0b4 100644
--- a/target/riscv/cpu_bits.h
+++ b/target/riscv/cpu_bits.h
@@ -315,6 +315,7 @@
  #define SMSTATEEN0_CS   (1ULL << 0)
  #define SMSTATEEN0_FCSR (1ULL << 1)
  #define SMSTATEEN0_JVT  (1ULL << 2)
+#define SMSTATEEN0_P1P13(1ULL << 56)
  #define SMSTATEEN0_HSCONTXT (1ULL << 57)
  #define SMSTATEEN0_IMSIC(1ULL << 58)
  #define SMSTATEEN0_AIA  (1ULL << 59)
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index 6b460ee0e8..d844ce770e 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -2248,6 +2248,11 @@ static RISCVException write_mstateen0(CPURISCVState 
*env, int csrno,
  wr_mask |= SMSTATEEN0_FCSR;
  }
  
+RISCVCPU *cpu = env_archcpu(env);

+if (cpu->env.priv_ver >= PRIV_VERSION_1_13_0) {

Why not use env directly?

+wr_mask |= SMSTATEEN0_P1P13;
+}
+
  return write_mstateen(env, csrno, wr_mask, new_val);
  }
  
@@ -2283,6 +2288,11 @@ static RISCVException write_mstateen0h(CPURISCVState *env, int csrno,

  {
  uint64_t wr_mask = SMSTATEEN_STATEEN | SMSTATEEN0_HSENVCFG;
  
+RISCVCPU *cpu = env_archcpu(env);

+if (cpu->env.priv_ver >= PRIV_VERSION_1_13_0) {

Same here.

+wr_mask |= SMSTATEEN0_P1P13;


Indent.

Zhiwei


+}
+
  return write_mstateenh(env, csrno, wr_mask, new_val);
  }
  




Re: [PATCH 4/5] target/riscv: Add MEDELEGH, HEDELEGH csrs for RV32

2024-05-12 Thread LIU Zhiwei



On 2024/5/10 14:58, Fea.Wang wrote:

Based on privileged spec 1.13, the RV32 needs to implement MEDELEGH
and HEDELEGH for exception codes 32-47 for reserving and exception codes
48-63 for custom use. Add the CSR number though the implementation is
just reading zero and writing ignore. Besides, for accessing HEDELEGH, it
should be controlled by mstateen0 'P1P13' bit.

Signed-off-by: Fea.Wang 
Reviewed-by: Frank Chang 
---
  target/riscv/cpu_bits.h |  2 ++
  target/riscv/csr.c  | 31 +++
  2 files changed, 33 insertions(+)

diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h
index 28bd3fb0b4..f888025c59 100644
--- a/target/riscv/cpu_bits.h
+++ b/target/riscv/cpu_bits.h
@@ -156,6 +156,8 @@
  
  /* 32-bit only */

  #define CSR_MSTATUSH0x310
+#define CSR_MEDELEGH0x312
+#define CSR_HEDELEGH0x612
  
  /* Machine Trap Handling */

  #define CSR_MSCRATCH0x340
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index d844ce770e..4d7313f456 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -3227,6 +3227,33 @@ static RISCVException write_hedeleg(CPURISCVState *env, 
int csrno,
  return RISCV_EXCP_NONE;
  }
  
+static RISCVException read_hedelegh(CPURISCVState *env, int csrno,

+   target_ulong *val)
+{
+RISCVException ret;
+ret = smstateen_acc_ok(env, 0, SMSTATEEN0_P1P13);
+if (ret != RISCV_EXCP_NONE) {
+return ret;
+}
+
+/* Reserved, now read zero */
+*val = 0;
+return RISCV_EXCP_NONE;
+}
+
+static RISCVException write_hedelegh(CPURISCVState *env, int csrno,
+target_ulong val)
+{
+RISCVException ret;
+ret = smstateen_acc_ok(env, 0, SMSTATEEN0_P1P13);
+if (ret != RISCV_EXCP_NONE) {
+return ret;
+}
+
+/* Reserved, now write ignore */
+return RISCV_EXCP_NONE;
+}
+
  static RISCVException rmw_hvien64(CPURISCVState *env, int csrno,
  uint64_t *ret_val,
  uint64_t new_val, uint64_t wr_mask)
@@ -4674,6 +4701,10 @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = {
  
  [CSR_MSTATUSH]= { "mstatush",   any32, read_mstatush,

write_mstatush   },
+[CSR_MEDELEGH]= { "medelegh",   any32, read_zero, write_ignore,
+  .min_priv_ver = PRIV_VERSION_1_13_0  },
+[CSR_HEDELEGH]= { "hedelegh",   any32, read_hedelegh, write_hedelegh,


Using hmode32 instead of any32.

Otherwise,

Reviewed-by: LIU Zhiwei 


+  .min_priv_ver = PRIV_VERSION_1_13_0  },
  
  /* Machine Trap Handling */

  [CSR_MSCRATCH] = { "mscratch", any,  read_mscratch, write_mscratch,




Re: [PATCH 5/5] target/riscv: Reserve exception codes for sw-check and hw-err

2024-05-12 Thread LIU Zhiwei



On 2024/5/10 14:58, Fea.Wang wrote:

Based on the priv-1.13.0, add the exception codes for Software-check and
Hardware-error.

Signed-off-by: Fea.Wang 
Reviewed-by: Frank Chang 
---
  target/riscv/cpu_bits.h | 2 ++
  1 file changed, 2 insertions(+)

diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h
index f888025c59..f037f727d9 100644
--- a/target/riscv/cpu_bits.h
+++ b/target/riscv/cpu_bits.h
@@ -673,6 +673,8 @@ typedef enum RISCVException {
  RISCV_EXCP_INST_PAGE_FAULT = 0xc, /* since: priv-1.10.0 */
  RISCV_EXCP_LOAD_PAGE_FAULT = 0xd, /* since: priv-1.10.0 */
  RISCV_EXCP_STORE_PAGE_FAULT = 0xf, /* since: priv-1.10.0 */
+RISCV_EXCP_SW_CHECK = 0x12, /* since: priv-1.13.0 */
+RISCV_EXCP_HW_ERR = 0x13, /* since: priv-1.13.0 */


Reviewed-by: LIU Zhiwei 

Zhiwei


  RISCV_EXCP_INST_GUEST_PAGE_FAULT = 0x14,
  RISCV_EXCP_LOAD_GUEST_ACCESS_FAULT = 0x15,
  RISCV_EXCP_VIRT_INSTRUCTION_FAULT = 0x16,




[PATCH v7 44/61] target/ppc/mmu_common.c: Remove hash field from mmu_ctx_t

2024-05-12 Thread BALATON Zoltan
Return hash value via a parameter and remove it from mmu_ctx.t.

Signed-off-by: BALATON Zoltan 
---
 target/ppc/mmu_common.c | 19 ---
 1 file changed, 8 insertions(+), 11 deletions(-)

diff --git a/target/ppc/mmu_common.c b/target/ppc/mmu_common.c
index 07c127d673..ccacc70ba6 100644
--- a/target/ppc/mmu_common.c
+++ b/target/ppc/mmu_common.c
@@ -41,7 +41,6 @@
 typedef struct {
 hwaddr raddr;  /* Real address */
 int prot;  /* Protection bits  */
-hwaddr hash[2];/* Pagetable hash values*/
 target_ulong ptem; /* Virtual segment ID | API */
 int key;   /* Access key   */
 int nx;/* Non-execute area */
@@ -316,7 +315,7 @@ static int get_bat_6xx_tlb(CPUPPCState *env, mmu_ctx_t *ctx,
 }
 
 static int mmu6xx_get_physical_address(CPUPPCState *env, mmu_ctx_t *ctx,
-   target_ulong eaddr,
+   target_ulong eaddr, hwaddr *hashp,
MMUAccessType access_type, int type)
 {
 PowerPCCPU *cpu = env_archcpu(env);
@@ -364,8 +363,7 @@ static int mmu6xx_get_physical_address(CPUPPCState *env, 
mmu_ctx_t *ctx,
 qemu_log_mask(CPU_LOG_MMU, "htab_base " HWADDR_FMT_plx " htab_mask "
   HWADDR_FMT_plx " hash " HWADDR_FMT_plx "\n",
   ppc_hash32_hpt_base(cpu), ppc_hash32_hpt_mask(cpu), 
hash);
-ctx->hash[0] = hash;
-ctx->hash[1] = ~hash;
+*hashp = hash;
 
 /* Initialize real address with an invalid value */
 ctx->raddr = (hwaddr)-1ULL;
@@ -746,8 +744,8 @@ static bool ppc_6xx_xlate(PowerPCCPU *cpu, vaddr eaddr,
 CPUState *cs = CPU(cpu);
 CPUPPCState *env = >env;
 mmu_ctx_t ctx;
-int type;
-int ret;
+hwaddr hash = 0; /* init to 0 to avoid used uninit warning */
+int type, ret;
 
 if (ppc_real_mode_xlate(cpu, eaddr, access_type, raddrp, psizep, protp)) {
 return true;
@@ -764,9 +762,8 @@ static bool ppc_6xx_xlate(PowerPCCPU *cpu, vaddr eaddr,
 }
 
 ctx.prot = 0;
-ctx.hash[0] = 0;
-ctx.hash[1] = 0;
-ret = mmu6xx_get_physical_address(env, , eaddr, access_type, type);
+ret = mmu6xx_get_physical_address(env, , eaddr, ,
+  access_type, type);
 if (ret == 0) {
 *raddrp = ctx.raddr;
 *protp = ctx.prot;
@@ -819,9 +816,9 @@ static bool ppc_6xx_xlate(PowerPCCPU *cpu, vaddr eaddr,
 tlb_miss:
 env->error_code |= ctx.key << 19;
 env->spr[SPR_HASH1] = ppc_hash32_hpt_base(cpu) +
-  get_pteg_offset32(cpu, ctx.hash[0]);
+  get_pteg_offset32(cpu, hash);
 env->spr[SPR_HASH2] = ppc_hash32_hpt_base(cpu) +
-  get_pteg_offset32(cpu, ctx.hash[1]);
+  get_pteg_offset32(cpu, ~hash);
 break;
 case -2:
 /* Access rights violation */
-- 
2.30.9




[PATCH v7 36/61] target/ppc/mmu_common.c: Remove local name for a constant

2024-05-12 Thread BALATON Zoltan
The mmask local variable is a less descriptive local name for a
constant. Drop it and use the constant directly in the two places it
is needed.

Signed-off-by: BALATON Zoltan 
---
 target/ppc/mmu_common.c | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/target/ppc/mmu_common.c b/target/ppc/mmu_common.c
index 9e0bfbda67..5d0090014a 100644
--- a/target/ppc/mmu_common.c
+++ b/target/ppc/mmu_common.c
@@ -98,7 +98,7 @@ static int ppc6xx_tlb_pte_check(mmu_ctx_t *ctx, target_ulong 
pte0,
 target_ulong pte1, int h,
 MMUAccessType access_type)
 {
-target_ulong ptem, mmask;
+target_ulong ptem;
 int ret, pteh, ptev, pp;
 
 ret = -1;
@@ -108,12 +108,11 @@ static int ppc6xx_tlb_pte_check(mmu_ctx_t *ctx, 
target_ulong pte0,
 if (ptev && h == pteh) {
 /* Check vsid & api */
 ptem = pte0 & PTE_PTEM_MASK;
-mmask = PTE_CHECK_MASK;
 pp = pte1 & 0x0003;
 if (ptem == ctx->ptem) {
 if (ctx->raddr != (hwaddr)-1ULL) {
 /* all matches should have equal RPN, WIMG & PP */
-if ((ctx->raddr & mmask) != (pte1 & mmask)) {
+if ((ctx->raddr & PTE_CHECK_MASK) != (pte1 & PTE_CHECK_MASK)) {
 qemu_log_mask(CPU_LOG_MMU, "Bad RPN/WIMG/PP\n");
 return -3;
 }
-- 
2.30.9




[PATCH v7 21/61] target/ppc/mmu_common.c: Split off BookE handling from ppc_jumbo_xlate()

2024-05-12 Thread BALATON Zoltan
Introduce ppc_booke_xlate() to handle BookE and BookE 2.06 cases to
reduce ppc_jumbo_xlate() further.

Signed-off-by: BALATON Zoltan 
Reviewed-by: Nicholas Piggin 
---
 target/ppc/mmu_common.c | 146 ++--
 1 file changed, 96 insertions(+), 50 deletions(-)

diff --git a/target/ppc/mmu_common.c b/target/ppc/mmu_common.c
index 6c6c7c55b6..09a780bb7a 100644
--- a/target/ppc/mmu_common.c
+++ b/target/ppc/mmu_common.c
@@ -1117,21 +1117,9 @@ int get_physical_address_wtlb(CPUPPCState *env, 
mmu_ctx_t *ctx,
  MMUAccessType access_type, int type,
  int mmu_idx)
 {
-bool real_mode;
-
-if (env->mmu_model == POWERPC_MMU_BOOKE) {
-return mmubooke_get_physical_address(env, >raddr, >prot,
- eaddr, access_type);
-} else if (env->mmu_model == POWERPC_MMU_BOOKE206) {
-return mmubooke206_get_physical_address(env, >raddr, >prot,
-eaddr, access_type, mmu_idx);
-}
-
-real_mode = (type == ACCESS_CODE) ? !FIELD_EX64(env->msr, MSR, IR)
-  : !FIELD_EX64(env->msr, MSR, DR);
-if (real_mode && (env->mmu_model == POWERPC_MMU_SOFT_6xx ||
-  env->mmu_model == POWERPC_MMU_SOFT_4xx ||
-  env->mmu_model == POWERPC_MMU_REAL)) {
+bool real_mode = (type == ACCESS_CODE) ? !FIELD_EX64(env->msr, MSR, IR)
+   : !FIELD_EX64(env->msr, MSR, DR);
+if (real_mode) {
 ctx->raddr = eaddr;
 ctx->prot = PAGE_RWX;
 return 0;
@@ -1205,6 +1193,93 @@ static void booke206_update_mas_tlb_miss(CPUPPCState 
*env, target_ulong address,
 env->spr[SPR_BOOKE_MAS0] |= env->last_way << MAS0_NV_SHIFT;
 }
 
+static bool ppc_booke_xlate(PowerPCCPU *cpu, vaddr eaddr,
+MMUAccessType access_type,
+hwaddr *raddrp, int *psizep, int *protp,
+int mmu_idx, bool guest_visible)
+{
+CPUState *cs = CPU(cpu);
+CPUPPCState *env = >env;
+hwaddr raddr;
+int prot, ret;
+
+if (env->mmu_model == POWERPC_MMU_BOOKE206) {
+ret = mmubooke206_get_physical_address(env, , , eaddr,
+   access_type, mmu_idx);
+} else {
+ret = mmubooke_get_physical_address(env, , , eaddr,
+access_type);
+}
+if (ret == 0) {
+*raddrp = raddr;
+*protp = prot;
+*psizep = TARGET_PAGE_BITS;
+return true;
+} else if (!guest_visible) {
+return false;
+}
+
+log_cpu_state_mask(CPU_LOG_MMU, cs, 0);
+if (access_type == MMU_INST_FETCH) {
+switch (ret) {
+case -1:
+/* No matches in page tables or TLB */
+switch (env->mmu_model) {
+case POWERPC_MMU_BOOKE206:
+booke206_update_mas_tlb_miss(env, eaddr, access_type, mmu_idx);
+/* fall through */
+case POWERPC_MMU_BOOKE:
+cs->exception_index = POWERPC_EXCP_ITLB;
+env->error_code = 0;
+env->spr[SPR_BOOKE_DEAR] = eaddr;
+env->spr[SPR_BOOKE_ESR] = mmubooke206_esr(mmu_idx, 
access_type);
+break;
+default:
+g_assert_not_reached();
+}
+break;
+case -2:
+/* Access rights violation */
+cs->exception_index = POWERPC_EXCP_ISI;
+env->error_code = 0;
+break;
+case -3:
+/* No execute protection violation */
+cs->exception_index = POWERPC_EXCP_ISI;
+env->spr[SPR_BOOKE_ESR] = 0;
+env->error_code = 0;
+break;
+}
+} else {
+switch (ret) {
+case -1:
+/* No matches in page tables or TLB */
+switch (env->mmu_model) {
+case POWERPC_MMU_BOOKE206:
+booke206_update_mas_tlb_miss(env, eaddr, access_type, mmu_idx);
+/* fall through */
+case POWERPC_MMU_BOOKE:
+cs->exception_index = POWERPC_EXCP_DTLB;
+env->error_code = 0;
+env->spr[SPR_BOOKE_DEAR] = eaddr;
+env->spr[SPR_BOOKE_ESR] = mmubooke206_esr(mmu_idx, 
access_type);
+break;
+default:
+g_assert_not_reached();
+}
+break;
+case -2:
+/* Access rights violation */
+cs->exception_index = POWERPC_EXCP_DSI;
+env->error_code = 0;
+env->spr[SPR_BOOKE_DEAR] = eaddr;
+env->spr[SPR_BOOKE_ESR] = mmubooke206_esr(mmu_idx, access_type);
+break;
+}
+}
+return false;
+}
+
 /* Perform address translation */
 /* TODO: Split this by mmu_model. */
 

[PATCH v7 05/61] target/ppc/mmu_common.c: Simplify checking for real mode

2024-05-12 Thread BALATON Zoltan
In get_physical_address_wtlb() the real_mode flag depends on either
the MSR[IR] or MSR[DR] bit depending on access_type. Extract just the
needed bit in a more straight forward way instead of doing unnecessary
computation.

Signed-off-by: BALATON Zoltan 
Reviewed-by: Nicholas Piggin 
---
 target/ppc/mmu_common.c | 6 --
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/target/ppc/mmu_common.c b/target/ppc/mmu_common.c
index 09cbeb0052..886fb6a657 100644
--- a/target/ppc/mmu_common.c
+++ b/target/ppc/mmu_common.c
@@ -1184,8 +1184,10 @@ int get_physical_address_wtlb(CPUPPCState *env, 
mmu_ctx_t *ctx,
  int mmu_idx)
 {
 int ret = -1;
-bool real_mode = (type == ACCESS_CODE && !FIELD_EX64(env->msr, MSR, IR)) ||
- (type != ACCESS_CODE && !FIELD_EX64(env->msr, MSR, DR));
+bool real_mode;
+
+real_mode = (type == ACCESS_CODE) ? !FIELD_EX64(env->msr, MSR, IR)
+  : !FIELD_EX64(env->msr, MSR, DR);
 
 switch (env->mmu_model) {
 case POWERPC_MMU_SOFT_6xx:
-- 
2.30.9




[PATCH v7 17/61] target/ppc/mmu_common.c: Don't use mmu_ctx_t for mmu40x_get_physical_address()

2024-05-12 Thread BALATON Zoltan
mmu40x_get_physical_address() only uses the raddr and prot fields from
mmu_ctx_t. Pass these directly instead of using a ctx struct.

Signed-off-by: BALATON Zoltan 
Reviewed-by: Nicholas Piggin 
---
 target/ppc/mmu_common.c | 37 +++--
 1 file changed, 15 insertions(+), 22 deletions(-)

diff --git a/target/ppc/mmu_common.c b/target/ppc/mmu_common.c
index 6570b280ca..adce6cceb8 100644
--- a/target/ppc/mmu_common.c
+++ b/target/ppc/mmu_common.c
@@ -519,20 +519,18 @@ int ppcemb_tlb_search(CPUPPCState *env, target_ulong 
address, uint32_t pid)
 return -1;
 }
 
-static int mmu40x_get_physical_address(CPUPPCState *env, mmu_ctx_t *ctx,
-   target_ulong address,
+static int mmu40x_get_physical_address(CPUPPCState *env, hwaddr *raddr,
+   int *prot, target_ulong address,
MMUAccessType access_type)
 {
 ppcemb_tlb_t *tlb;
-hwaddr raddr;
 int i, ret, zsel, zpr, pr;
 
 ret = -1;
-raddr = (hwaddr)-1ULL;
 pr = FIELD_EX64(env->msr, MSR, PR);
 for (i = 0; i < env->nb_tlb; i++) {
 tlb = >tlb.tlbe[i];
-if (!ppcemb_tlb_check(env, tlb, , address,
+if (!ppcemb_tlb_check(env, tlb, raddr, address,
   env->spr[SPR_40x_PID], i)) {
 continue;
 }
@@ -550,40 +548,34 @@ static int mmu40x_get_physical_address(CPUPPCState *env, 
mmu_ctx_t *ctx,
 /* fall through */
 case 0x3:
 /* All accesses granted */
-ctx->prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
+*prot = PAGE_RWX;
 ret = 0;
 break;
+
 case 0x0:
 if (pr != 0) {
 /* Raise Zone protection fault.  */
 env->spr[SPR_40x_ESR] = 1 << 22;
-ctx->prot = 0;
+*prot = 0;
 ret = -2;
 break;
 }
 /* fall through */
 case 0x1:
-check_perms:
+check_perms:
 /* Check from TLB entry */
-ctx->prot = tlb->prot;
-ret = check_prot(ctx->prot, access_type);
+*prot = tlb->prot;
+ret = check_prot(*prot, access_type);
 if (ret == -2) {
 env->spr[SPR_40x_ESR] = 0;
 }
 break;
 }
-if (ret >= 0) {
-ctx->raddr = raddr;
-qemu_log_mask(CPU_LOG_MMU, "%s: access granted " TARGET_FMT_lx
-  " => " HWADDR_FMT_plx
-  " %d %d\n", __func__, address, ctx->raddr, ctx->prot,
-  ret);
-return 0;
-}
 }
-qemu_log_mask(CPU_LOG_MMU, "%s: access refused " TARGET_FMT_lx
-  " => " HWADDR_FMT_plx " %d %d\n",
-  __func__, address, raddr, ctx->prot, ret);
+qemu_log_mask(CPU_LOG_MMU, "%s: access %s " TARGET_FMT_lx " => "
+  HWADDR_FMT_plx " %d %d\n",  __func__,
+  ret < 0 ? "refused" : "granted", address,
+  ret < 0 ? 0 : *raddr, *prot, ret);
 
 return ret;
 }
@@ -1171,7 +1163,8 @@ int get_physical_address_wtlb(CPUPPCState *env, mmu_ctx_t 
*ctx,
 case POWERPC_MMU_SOFT_6xx:
 return mmu6xx_get_physical_address(env, ctx, eaddr, access_type, type);
 case POWERPC_MMU_SOFT_4xx:
-return mmu40x_get_physical_address(env, ctx, eaddr, access_type);
+return mmu40x_get_physical_address(env, >raddr, >prot, eaddr,
+   access_type);
 case POWERPC_MMU_REAL:
 cpu_abort(env_cpu(env),
   "PowerPC in real mode do not do any translation\n");
-- 
2.30.9




[PATCH v7 37/61] target/ppc/mmu_common.c: Remove single use local variable

2024-05-12 Thread BALATON Zoltan
The ptem variable in ppc6xx_tlb_pte_check() is used only once,
simplify by removing it as the value is already clear itself without
adding a local name for it.

Signed-off-by: BALATON Zoltan 
---
 target/ppc/mmu_common.c | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/target/ppc/mmu_common.c b/target/ppc/mmu_common.c
index 5d0090014a..4ca700e31b 100644
--- a/target/ppc/mmu_common.c
+++ b/target/ppc/mmu_common.c
@@ -98,7 +98,6 @@ static int ppc6xx_tlb_pte_check(mmu_ctx_t *ctx, target_ulong 
pte0,
 target_ulong pte1, int h,
 MMUAccessType access_type)
 {
-target_ulong ptem;
 int ret, pteh, ptev, pp;
 
 ret = -1;
@@ -107,9 +106,8 @@ static int ppc6xx_tlb_pte_check(mmu_ctx_t *ctx, 
target_ulong pte0,
 pteh = (pte0 >> 6) & 1;
 if (ptev && h == pteh) {
 /* Check vsid & api */
-ptem = pte0 & PTE_PTEM_MASK;
 pp = pte1 & 0x0003;
-if (ptem == ctx->ptem) {
+if ((pte0 & PTE_PTEM_MASK) == ctx->ptem) {
 if (ctx->raddr != (hwaddr)-1ULL) {
 /* all matches should have equal RPN, WIMG & PP */
 if ((ctx->raddr & PTE_CHECK_MASK) != (pte1 & PTE_CHECK_MASK)) {
-- 
2.30.9




[PATCH v7 14/61] target/ppc/mmu_common.c: Fix misindented qemu_log_mask() calls

2024-05-12 Thread BALATON Zoltan
Fix several qemu_log_mask() calls that are misindented.

Signed-off-by: BALATON Zoltan 
Acked-by: Nicholas Piggin 
---
 target/ppc/mmu_common.c | 42 -
 1 file changed, 20 insertions(+), 22 deletions(-)

diff --git a/target/ppc/mmu_common.c b/target/ppc/mmu_common.c
index 2f412dd7c5..124148b3da 100644
--- a/target/ppc/mmu_common.c
+++ b/target/ppc/mmu_common.c
@@ -315,8 +315,8 @@ static int get_bat_6xx_tlb(CPUPPCState *env, mmu_ctx_t *ctx,
 int ret = -1;
 bool ifetch = access_type == MMU_INST_FETCH;
 
- qemu_log_mask(CPU_LOG_MMU, "%s: %cBAT v " TARGET_FMT_lx "\n", __func__,
- ifetch ? 'I' : 'D', virtual);
+qemu_log_mask(CPU_LOG_MMU, "%s: %cBAT v " TARGET_FMT_lx "\n", __func__,
+  ifetch ? 'I' : 'D', virtual);
 if (ifetch) {
 BATlt = env->IBAT[1];
 BATut = env->IBAT[0];
@@ -330,9 +330,9 @@ static int get_bat_6xx_tlb(CPUPPCState *env, mmu_ctx_t *ctx,
 BEPIu = *BATu & 0xF000;
 BEPIl = *BATu & 0x0FFE;
 bat_size_prot(env, , , , BATu, BATl);
- qemu_log_mask(CPU_LOG_MMU, "%s: %cBAT%d v " TARGET_FMT_lx " BATu "
-   TARGET_FMT_lx " BATl " TARGET_FMT_lx "\n", __func__,
-   ifetch ? 'I' : 'D', i, virtual, *BATu, *BATl);
+qemu_log_mask(CPU_LOG_MMU, "%s: %cBAT%d v " TARGET_FMT_lx " BATu "
+  TARGET_FMT_lx " BATl " TARGET_FMT_lx "\n", __func__,
+  ifetch ? 'I' : 'D', i, virtual, *BATu, *BATl);
 if ((virtual & 0xF000) == BEPIu &&
 ((virtual & 0x0FFE) & ~bl) == BEPIl) {
 /* BAT matches */
@@ -364,12 +364,11 @@ static int get_bat_6xx_tlb(CPUPPCState *env, mmu_ctx_t 
*ctx,
 BEPIu = *BATu & 0xF000;
 BEPIl = *BATu & 0x0FFE;
 bl = (*BATu & 0x1FFC) << 15;
- qemu_log_mask(CPU_LOG_MMU, "%s: %cBAT%d v "
-   TARGET_FMT_lx " BATu " TARGET_FMT_lx
-   " BATl " TARGET_FMT_lx "\n\t" TARGET_FMT_lx " "
-   TARGET_FMT_lx " " TARGET_FMT_lx "\n",
-   __func__, ifetch ? 'I' : 'D', i, virtual,
-   *BATu, *BATl, BEPIu, BEPIl, bl);
+qemu_log_mask(CPU_LOG_MMU, "%s: %cBAT%d v " TARGET_FMT_lx
+  " BATu " TARGET_FMT_lx " BATl " TARGET_FMT_lx
+  "\n\t" TARGET_FMT_lx " " TARGET_FMT_lx " "
+  TARGET_FMT_lx "\n", __func__, ifetch ? 'I' : 'D',
+  i, virtual, *BATu, *BATl, BEPIu, BEPIl, bl);
 }
 }
 }
@@ -415,9 +414,8 @@ static int mmu6xx_get_physical_address(CPUPPCState *env, 
mmu_ctx_t *ctx,
 hash = vsid ^ pgidx;
 ctx->ptem = (vsid << 7) | (pgidx >> 10);
 
-qemu_log_mask(CPU_LOG_MMU,
-"pte segment: key=%d ds %d nx %d vsid " TARGET_FMT_lx "\n",
-ctx->key, ds, ctx->nx, vsid);
+qemu_log_mask(CPU_LOG_MMU, "pte segment: key=%d ds %d nx %d vsid "
+  TARGET_FMT_lx "\n", ctx->key, ds, ctx->nx, vsid);
 if (!ds) {
 /* Check if instruction fetch is allowed, if needed */
 if (type == ACCESS_CODE && ctx->nx) {
@@ -583,9 +581,9 @@ static int mmu40x_get_physical_address(CPUPPCState *env, 
mmu_ctx_t *ctx,
 return 0;
 }
 }
- qemu_log_mask(CPU_LOG_MMU, "%s: access refused " TARGET_FMT_lx
-   " => " HWADDR_FMT_plx
-   " %d %d\n", __func__, address, raddr, ctx->prot, ret);
+qemu_log_mask(CPU_LOG_MMU, "%s: access refused " TARGET_FMT_lx
+  " => " HWADDR_FMT_plx " %d %d\n",
+  __func__, address, raddr, ctx->prot, ret);
 
 return ret;
 }
@@ -704,11 +702,11 @@ int ppcmas_tlb_check(CPUPPCState *env, ppcmas_tlb_t *tlb, 
hwaddr *raddrp,
 }
 
 mask = ~(booke206_tlb_to_page_size(env, tlb) - 1);
- qemu_log_mask(CPU_LOG_MMU, "%s: TLB ADDR=0x" TARGET_FMT_lx
-   " PID=0x%x MAS1=0x%x MAS2=0x%" PRIx64 " mask=0x%"
-   HWADDR_PRIx " MAS7_3=0x%" PRIx64 " MAS8=0x%" PRIx32 "\n",
-   __func__, address, pid, tlb->mas1, tlb->mas2, mask,
-   tlb->mas7_3, tlb->mas8);
+qemu_log_mask(CPU_LOG_MMU, "%s: TLB ADDR=0x" TARGET_FMT_lx
+  " PID=0x%x MAS1=0x%x MAS2=0x%" PRIx64 " mask=0x%"
+  HWADDR_PRIx " MAS7_3=0x%" PRIx64 " MAS8=0x%" PRIx32 "\n",
+  __func__, address, pid, tlb->mas1, tlb->mas2, mask,
+  tlb->mas7_3, tlb->mas8);
 
 /* Check PID */
 tlb_pid = (tlb->mas1 & MAS1_TID_MASK) >> MAS1_TID_SHIFT;
-- 
2.30.9




[PATCH v7 04/61] target/ppc/mmu_common.c: Remove unneeded local variable

2024-05-12 Thread BALATON Zoltan
In mmubooke_check_tlb() and mmubooke206_check_tlb() we can assign the
value of prot2 directly to the destination, no need to have a separate
local variable for it.

Signed-off-by: BALATON Zoltan 
Reviewed-by: Nicholas Piggin 
---
 target/ppc/mmu_common.c | 30 +-
 1 file changed, 13 insertions(+), 17 deletions(-)

diff --git a/target/ppc/mmu_common.c b/target/ppc/mmu_common.c
index f79e390306..09cbeb0052 100644
--- a/target/ppc/mmu_common.c
+++ b/target/ppc/mmu_common.c
@@ -628,8 +628,6 @@ static int mmubooke_check_tlb(CPUPPCState *env, 
ppcemb_tlb_t *tlb,
   hwaddr *raddr, int *prot, target_ulong address,
   MMUAccessType access_type, int i)
 {
-int prot2;
-
 if (!mmubooke_check_pid(env, tlb, raddr, address, i)) {
 qemu_log_mask(CPU_LOG_MMU, "%s: TLB entry not found\n", __func__);
 return -1;
@@ -644,17 +642,16 @@ static int mmubooke_check_tlb(CPUPPCState *env, 
ppcemb_tlb_t *tlb,
 }
 
 if (FIELD_EX64(env->msr, MSR, PR)) {
-prot2 = tlb->prot & 0xF;
+*prot = tlb->prot & 0xF;
 } else {
-prot2 = (tlb->prot >> 4) & 0xF;
+*prot = (tlb->prot >> 4) & 0xF;
 }
-*prot = prot2;
-if (prot2 & prot_for_access_type(access_type)) {
+if (*prot & prot_for_access_type(access_type)) {
 qemu_log_mask(CPU_LOG_MMU, "%s: good TLB!\n", __func__);
 return 0;
 }
 
-qemu_log_mask(CPU_LOG_MMU, "%s: no prot match: %x\n", __func__, prot2);
+qemu_log_mask(CPU_LOG_MMU, "%s: no prot match: %x\n", __func__, *prot);
 return access_type == MMU_INST_FETCH ? -3 : -2;
 }
 
@@ -795,7 +792,6 @@ static int mmubooke206_check_tlb(CPUPPCState *env, 
ppcmas_tlb_t *tlb,
  target_ulong address,
  MMUAccessType access_type, int mmu_idx)
 {
-int prot2 = 0;
 uint32_t epid;
 bool as, pr;
 bool use_epid = mmubooke206_get_as(env, mmu_idx, , , );
@@ -841,34 +837,34 @@ found_tlb:
 return -1;
 }
 
+*prot = 0;
 if (pr) {
 if (tlb->mas7_3 & MAS3_UR) {
-prot2 |= PAGE_READ;
+*prot |= PAGE_READ;
 }
 if (tlb->mas7_3 & MAS3_UW) {
-prot2 |= PAGE_WRITE;
+*prot |= PAGE_WRITE;
 }
 if (tlb->mas7_3 & MAS3_UX) {
-prot2 |= PAGE_EXEC;
+*prot |= PAGE_EXEC;
 }
 } else {
 if (tlb->mas7_3 & MAS3_SR) {
-prot2 |= PAGE_READ;
+*prot |= PAGE_READ;
 }
 if (tlb->mas7_3 & MAS3_SW) {
-prot2 |= PAGE_WRITE;
+*prot |= PAGE_WRITE;
 }
 if (tlb->mas7_3 & MAS3_SX) {
-prot2 |= PAGE_EXEC;
+*prot |= PAGE_EXEC;
 }
 }
-*prot = prot2;
-if (prot2 & prot_for_access_type(access_type)) {
+if (*prot & prot_for_access_type(access_type)) {
 qemu_log_mask(CPU_LOG_MMU, "%s: good TLB!\n", __func__);
 return 0;
 }
 
-qemu_log_mask(CPU_LOG_MMU, "%s: no prot match: %x\n", __func__, prot2);
+qemu_log_mask(CPU_LOG_MMU, "%s: no prot match: %x\n", __func__, *prot);
 return access_type == MMU_INST_FETCH ? -3 : -2;
 }
 
-- 
2.30.9




[PATCH v7 25/61] target/ppc/mmu_common.c: Split off 40x cases from ppc_jumbo_xlate()

2024-05-12 Thread BALATON Zoltan
Introduce ppc_40x_xlate() to split off 40x handlning leaving only 6xx
in ppc_jumbo_xlate() now.

Signed-off-by: BALATON Zoltan 
---
 target/ppc/mmu_common.c | 150 +---
 1 file changed, 93 insertions(+), 57 deletions(-)

diff --git a/target/ppc/mmu_common.c b/target/ppc/mmu_common.c
index ab912da821..ddb014e0aa 100644
--- a/target/ppc/mmu_common.c
+++ b/target/ppc/mmu_common.c
@@ -1258,6 +1258,74 @@ static bool ppc_real_mode_xlate(PowerPCCPU *cpu, vaddr 
eaddr,
 return false;
 }
 
+static bool ppc_40x_xlate(PowerPCCPU *cpu, vaddr eaddr,
+  MMUAccessType access_type,
+  hwaddr *raddrp, int *psizep, int *protp,
+  int mmu_idx, bool guest_visible)
+{
+CPUState *cs = CPU(cpu);
+CPUPPCState *env = >env;
+int ret;
+
+if (ppc_real_mode_xlate(cpu, eaddr, access_type, raddrp, psizep, protp)) {
+return true;
+}
+
+ret = mmu40x_get_physical_address(env, raddrp, protp, eaddr, access_type);
+if (ret == 0) {
+*psizep = TARGET_PAGE_BITS;
+return true;
+} else if (!guest_visible) {
+return false;
+}
+
+log_cpu_state_mask(CPU_LOG_MMU, cs, 0);
+if (access_type == MMU_INST_FETCH) {
+switch (ret) {
+case -1:
+/* No matches in page tables or TLB */
+cs->exception_index = POWERPC_EXCP_ITLB;
+env->error_code = 0;
+env->spr[SPR_40x_DEAR] = eaddr;
+env->spr[SPR_40x_ESR] = 0x;
+break;
+case -2:
+/* Access rights violation */
+cs->exception_index = POWERPC_EXCP_ISI;
+env->error_code = 0x0800;
+break;
+default:
+g_assert_not_reached();
+}
+} else {
+switch (ret) {
+case -1:
+/* No matches in page tables or TLB */
+cs->exception_index = POWERPC_EXCP_DTLB;
+env->error_code = 0;
+env->spr[SPR_40x_DEAR] = eaddr;
+if (access_type == MMU_DATA_STORE) {
+env->spr[SPR_40x_ESR] = 0x0080;
+} else {
+env->spr[SPR_40x_ESR] = 0x;
+}
+break;
+case -2:
+/* Access rights violation */
+cs->exception_index = POWERPC_EXCP_DSI;
+env->error_code = 0;
+env->spr[SPR_40x_DEAR] = eaddr;
+if (access_type == MMU_DATA_STORE) {
+env->spr[SPR_40x_ESR] |= 0x0080;
+}
+break;
+default:
+g_assert_not_reached();
+}
+}
+return false;
+}
+
 /* Perform address translation */
 /* TODO: Split this by mmu_model. */
 static bool ppc_jumbo_xlate(PowerPCCPU *cpu, vaddr eaddr,
@@ -1301,23 +1369,11 @@ static bool ppc_jumbo_xlate(PowerPCCPU *cpu, vaddr 
eaddr,
 switch (ret) {
 case -1:
 /* No matches in page tables or TLB */
-switch (env->mmu_model) {
-case POWERPC_MMU_SOFT_6xx:
-cs->exception_index = POWERPC_EXCP_IFTLB;
-env->error_code = 1 << 18;
-env->spr[SPR_IMISS] = eaddr;
-env->spr[SPR_ICMP] = 0x8000 | ctx.ptem;
-goto tlb_miss;
-case POWERPC_MMU_SOFT_4xx:
-cs->exception_index = POWERPC_EXCP_ITLB;
-env->error_code = 0;
-env->spr[SPR_40x_DEAR] = eaddr;
-env->spr[SPR_40x_ESR] = 0x;
-break;
-default:
-g_assert_not_reached();
-}
-break;
+cs->exception_index = POWERPC_EXCP_IFTLB;
+env->error_code = 1 << 18;
+env->spr[SPR_IMISS] = eaddr;
+env->spr[SPR_ICMP] = 0x8000 | ctx.ptem;
+goto tlb_miss;
 case -2:
 /* Access rights violation */
 cs->exception_index = POWERPC_EXCP_ISI;
@@ -1339,54 +1395,31 @@ static bool ppc_jumbo_xlate(PowerPCCPU *cpu, vaddr 
eaddr,
 switch (ret) {
 case -1:
 /* No matches in page tables or TLB */
-switch (env->mmu_model) {
-case POWERPC_MMU_SOFT_6xx:
-if (access_type == MMU_DATA_STORE) {
-cs->exception_index = POWERPC_EXCP_DSTLB;
-env->error_code = 1 << 16;
-} else {
-cs->exception_index = POWERPC_EXCP_DLTLB;
-env->error_code = 0;
-}
-env->spr[SPR_DMISS] = eaddr;
-env->spr[SPR_DCMP] = 0x8000 | ctx.ptem;
-tlb_miss:
-env->error_code |= ctx.key << 19;
-env->spr[SPR_HASH1] = ppc_hash32_hpt_base(cpu) +
-  get_pteg_offset32(cpu, ctx.hash[0]);
-env->spr[SPR_HASH2] = ppc_hash32_hpt_base(cpu) +
-  get_pteg_offset32(cpu, 

[PATCH v7 59/61] target/ppc/mmu_common.c: Stop using ctx in get_bat_6xx_tlb()

2024-05-12 Thread BALATON Zoltan
Pass raddr and prot in function parameters instead

Signed-off-by: BALATON Zoltan 
---
 target/ppc/mmu_common.c | 17 +
 1 file changed, 9 insertions(+), 8 deletions(-)

diff --git a/target/ppc/mmu_common.c b/target/ppc/mmu_common.c
index ba54c40048..6d588b6795 100644
--- a/target/ppc/mmu_common.c
+++ b/target/ppc/mmu_common.c
@@ -193,7 +193,7 @@ static int ppc6xx_tlb_check(CPUPPCState *env, hwaddr 
*raddr, int *prot,
 return ret;
 }
 
-static int get_bat_6xx_tlb(CPUPPCState *env, mmu_ctx_t *ctx,
+static int get_bat_6xx_tlb(CPUPPCState *env, hwaddr *raddr, int *prot,
target_ulong eaddr, MMUAccessType access_type,
bool pr)
 {
@@ -224,16 +224,16 @@ static int get_bat_6xx_tlb(CPUPPCState *env, mmu_ctx_t 
*ctx,
 if ((eaddr & BATU32_BEPIU) == BEPIu &&
 ((eaddr & BATU32_BEPIL) & ~bl) == BEPIl) {
 /* Get physical address */
-ctx->raddr = (*BATl & BATU32_BEPIU) |
+*raddr = (*BATl & BATU32_BEPIU) |
 ((eaddr & BATU32_BEPIL & bl) | (*BATl & BATU32_BEPIL)) |
 (eaddr & 0x0001F000);
 /* Compute access rights */
-ctx->prot = ppc_hash32_bat_prot(*BATu, *BATl);
-if (check_prot_access_type(ctx->prot, access_type)) {
+*prot = ppc_hash32_bat_prot(*BATu, *BATl);
+if (check_prot_access_type(*prot, access_type)) {
 qemu_log_mask(CPU_LOG_MMU, "BAT %d match: r " 
HWADDR_FMT_plx
-  " prot=%c%c\n", i, ctx->raddr,
-  ctx->prot & PAGE_READ ? 'R' : '-',
-  ctx->prot & PAGE_WRITE ? 'W' : '-');
+  " prot=%c%c\n", i, *raddr,
+  *prot & PAGE_READ ? 'R' : '-',
+  *prot & PAGE_WRITE ? 'W' : '-');
 ret = 0;
 } else {
 ret = -2;
@@ -277,7 +277,8 @@ static int mmu6xx_get_physical_address(CPUPPCState *env, 
mmu_ctx_t *ctx,
 
 /* First try to find a BAT entry if there are any */
 if (env->nb_BATs &&
-get_bat_6xx_tlb(env, ctx, eaddr, access_type, pr) == 0) {
+get_bat_6xx_tlb(env, >raddr, >prot, eaddr,
+access_type, pr) == 0) {
 return 0;
 }
 
-- 
2.30.9




[PATCH v7 32/61] target/ppc/mmu-radix64.c: Drop a local variable

2024-05-12 Thread BALATON Zoltan
The value is only used once so no need to introduce a local variable
for it.

Signed-off-by: BALATON Zoltan 
Reviewed-by: Nicholas Piggin 
---
 target/ppc/mmu-radix64.c | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/target/ppc/mmu-radix64.c b/target/ppc/mmu-radix64.c
index 8daf71d2db..395ce3b782 100644
--- a/target/ppc/mmu-radix64.c
+++ b/target/ppc/mmu-radix64.c
@@ -185,7 +185,6 @@ static bool ppc_radix64_check_prot(PowerPCCPU *cpu, 
MMUAccessType access_type,
int mmu_idx, bool partition_scoped)
 {
 CPUPPCState *env = >env;
-int need_prot;
 
 /* Check Page Attributes (pte58:59) */
 if ((pte & R_PTE_ATT) == R_PTE_ATT_NI_IO && access_type == MMU_INST_FETCH) 
{
@@ -210,8 +209,8 @@ static bool ppc_radix64_check_prot(PowerPCCPU *cpu, 
MMUAccessType access_type,
 }
 
 /* Check if requested access type is allowed */
-need_prot = prot_for_access_type(access_type);
-if (need_prot & ~*prot) { /* Page Protected for that Access */
+if (prot_for_access_type(access_type) & ~*prot) {
+/* Page Protected for that Access */
 *fault_cause |= access_type == MMU_INST_FETCH ? SRR1_NOEXEC_GUARD :
 DSISR_PROTFAULT;
 return true;
-- 
2.30.9




[PATCH v7 56/61] target/ppc/mmu_common.c: Rename function parameter

2024-05-12 Thread BALATON Zoltan
Rename parameter of get_bat_6xx_tlb() from virtual to eaddr to match
other functions.

Signed-off-by: BALATON Zoltan 
---
 target/ppc/mmu_common.c | 18 +-
 1 file changed, 9 insertions(+), 9 deletions(-)

diff --git a/target/ppc/mmu_common.c b/target/ppc/mmu_common.c
index 1137ec197b..fd8767879d 100644
--- a/target/ppc/mmu_common.c
+++ b/target/ppc/mmu_common.c
@@ -221,7 +221,7 @@ static inline void bat_size_prot(CPUPPCState *env, 
target_ulong *blp,
 }
 
 static int get_bat_6xx_tlb(CPUPPCState *env, mmu_ctx_t *ctx,
-   target_ulong virtual, MMUAccessType access_type)
+   target_ulong eaddr, MMUAccessType access_type)
 {
 target_ulong *BATlt, *BATut, *BATu, *BATl;
 target_ulong BEPIl, BEPIu, bl;
@@ -230,7 +230,7 @@ static int get_bat_6xx_tlb(CPUPPCState *env, mmu_ctx_t *ctx,
 bool ifetch = access_type == MMU_INST_FETCH;
 
 qemu_log_mask(CPU_LOG_MMU, "%s: %cBAT v " TARGET_FMT_lx "\n", __func__,
-  ifetch ? 'I' : 'D', virtual);
+  ifetch ? 'I' : 'D', eaddr);
 if (ifetch) {
 BATlt = env->IBAT[1];
 BATut = env->IBAT[0];
@@ -246,15 +246,15 @@ static int get_bat_6xx_tlb(CPUPPCState *env, mmu_ctx_t 
*ctx,
 bat_size_prot(env, , , , BATu, BATl);
 qemu_log_mask(CPU_LOG_MMU, "%s: %cBAT%d v " TARGET_FMT_lx " BATu "
   TARGET_FMT_lx " BATl " TARGET_FMT_lx "\n", __func__,
-  ifetch ? 'I' : 'D', i, virtual, *BATu, *BATl);
-if ((virtual & 0xF000) == BEPIu &&
-((virtual & 0x0FFE) & ~bl) == BEPIl) {
+  ifetch ? 'I' : 'D', i, eaddr, *BATu, *BATl);
+if ((eaddr & 0xF000) == BEPIu &&
+((eaddr & 0x0FFE) & ~bl) == BEPIl) {
 /* BAT matches */
 if (valid != 0) {
 /* Get physical address */
 ctx->raddr = (*BATl & 0xF000) |
-((virtual & 0x0FFE & bl) | (*BATl & 0x0FFE)) |
-(virtual & 0x0001F000);
+((eaddr & 0x0FFE & bl) | (*BATl & 0x0FFE)) |
+(eaddr & 0x0001F000);
 /* Compute access rights */
 ctx->prot = prot;
 if (check_prot_access_type(ctx->prot, access_type)) {
@@ -273,7 +273,7 @@ static int get_bat_6xx_tlb(CPUPPCState *env, mmu_ctx_t *ctx,
 if (ret < 0) {
 if (qemu_log_enabled()) {
 qemu_log_mask(CPU_LOG_MMU, "no BAT match for "
-  TARGET_FMT_lx ":\n", virtual);
+  TARGET_FMT_lx ":\n", eaddr);
 for (i = 0; i < 4; i++) {
 BATu = [i];
 BATl = [i];
@@ -284,7 +284,7 @@ static int get_bat_6xx_tlb(CPUPPCState *env, mmu_ctx_t *ctx,
   " BATu " TARGET_FMT_lx " BATl " TARGET_FMT_lx
   "\n\t" TARGET_FMT_lx " " TARGET_FMT_lx " "
   TARGET_FMT_lx "\n", __func__, ifetch ? 'I' : 'D',
-  i, virtual, *BATu, *BATl, BEPIu, BEPIl, bl);
+  i, eaddr, *BATu, *BATl, BEPIu, BEPIl, bl);
 }
 }
 }
-- 
2.30.9




[PATCH v7 48/61] target/ppc/mmu_common.c: Simplify a switch statement

2024-05-12 Thread BALATON Zoltan
In mmu6xx_get_physical_address() the switch handles all cases so the
default is never reached and can be dropped. Also group together cases
which just return -4.

Signed-off-by: BALATON Zoltan 
---
 target/ppc/mmu_common.c | 19 ---
 1 file changed, 4 insertions(+), 15 deletions(-)

diff --git a/target/ppc/mmu_common.c b/target/ppc/mmu_common.c
index 1a2b4158d5..f38a73464f 100644
--- a/target/ppc/mmu_common.c
+++ b/target/ppc/mmu_common.c
@@ -375,15 +375,6 @@ static int mmu6xx_get_physical_address(CPUPPCState *env, 
mmu_ctx_t *ctx,
 case ACCESS_INT:
 /* Integer load/store : only access allowed */
 break;
-case ACCESS_CODE:
-/* No code fetch is allowed in direct-store areas */
-return -4;
-case ACCESS_FLOAT:
-/* Floating point load/store */
-return -4;
-case ACCESS_RES:
-/* lwarx, ldarx or srwcx. */
-return -4;
 case ACCESS_CACHE:
 /*
  * dcba, dcbt, dcbtst, dcbf, dcbi, dcbst, dcbz, or icbi
@@ -393,12 +384,10 @@ static int mmu6xx_get_physical_address(CPUPPCState *env, 
mmu_ctx_t *ctx,
  */
 ctx->raddr = eaddr;
 return 0;
-case ACCESS_EXT:
-/* eciwx or ecowx */
-return -4;
-default:
-qemu_log_mask(CPU_LOG_MMU, "ERROR: instruction should not need address"
-   " translation\n");
+case ACCESS_CODE: /* No code fetch is allowed in direct-store areas */
+case ACCESS_FLOAT: /* Floating point load/store */
+case ACCESS_RES: /* lwarx, ldarx or srwcx. */
+case ACCESS_EXT: /* eciwx or ecowx */
 return -4;
 }
 if ((access_type == MMU_DATA_STORE || ctx->key != 1) &&
-- 
2.30.9




[PATCH v7 33/61] target/ppc: Add a function to check for page protection bit

2024-05-12 Thread BALATON Zoltan
Checking if a page protection bit is set for a given access type is a
common operation. Add a function to avoid repeating the same check at
multiple places. As this relies on access type and page protection bit
values having certain relation also add an assert to ensure that this
assumption holds.

Signed-off-by: BALATON Zoltan 
---
 target/ppc/cpu_init.c|  5 +
 target/ppc/internal.h| 23 +--
 target/ppc/mmu-hash32.c  |  6 +++---
 target/ppc/mmu-hash64.c  |  2 +-
 target/ppc/mmu-radix64.c |  2 +-
 target/ppc/mmu_common.c  | 26 +-
 6 files changed, 28 insertions(+), 36 deletions(-)

diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c
index 92c71b2a09..d3b92d9f0e 100644
--- a/target/ppc/cpu_init.c
+++ b/target/ppc/cpu_init.c
@@ -7388,6 +7388,11 @@ static void ppc_cpu_class_init(ObjectClass *oc, void 
*data)
 #ifndef CONFIG_USER_ONLY
 cc->sysemu_ops = _sysemu_ops;
 INTERRUPT_STATS_PROVIDER_CLASS(oc)->get_statistics = ppc_get_irq_stats;
+
+/* check_prot_access_type relies on MMU access and PAGE bits relations */
+qemu_build_assert(MMU_DATA_LOAD == 0 && MMU_DATA_STORE == 1 &&
+  MMU_INST_FETCH == 2 && PAGE_READ == 1 &&
+  PAGE_WRITE == 2 && PAGE_EXEC == 4);
 #endif
 
 cc->gdb_num_core_regs = 71;
diff --git a/target/ppc/internal.h b/target/ppc/internal.h
index 4a90dd2584..20fb2ec593 100644
--- a/target/ppc/internal.h
+++ b/target/ppc/internal.h
@@ -234,27 +234,14 @@ void destroy_ppc_opcodes(PowerPCCPU *cpu);
 void ppc_gdb_init(CPUState *cs, PowerPCCPUClass *ppc);
 const gchar *ppc_gdb_arch_name(CPUState *cs);
 
-/**
- * prot_for_access_type:
- * @access_type: Access type
- *
- * Return the protection bit required for the given access type.
- */
-static inline int prot_for_access_type(MMUAccessType access_type)
+#ifndef CONFIG_USER_ONLY
+
+/* Check if permission bit required for the access_type is set in prot */
+static inline int check_prot_access_type(int prot, MMUAccessType access_type)
 {
-switch (access_type) {
-case MMU_INST_FETCH:
-return PAGE_EXEC;
-case MMU_DATA_LOAD:
-return PAGE_READ;
-case MMU_DATA_STORE:
-return PAGE_WRITE;
-}
-g_assert_not_reached();
+return prot & (1 << access_type);
 }
 
-#ifndef CONFIG_USER_ONLY
-
 /* PowerPC MMU emulation */
 
 bool ppc_xlate(PowerPCCPU *cpu, vaddr eaddr, MMUAccessType access_type,
diff --git a/target/ppc/mmu-hash32.c b/target/ppc/mmu-hash32.c
index 3abaf16e78..1e8f1df0f0 100644
--- a/target/ppc/mmu-hash32.c
+++ b/target/ppc/mmu-hash32.c
@@ -252,7 +252,7 @@ static bool ppc_hash32_direct_store(PowerPCCPU *cpu, 
target_ulong sr,
 }
 
 *prot = key ? PAGE_READ | PAGE_WRITE : PAGE_READ;
-if (*prot & prot_for_access_type(access_type)) {
+if (check_prot_access_type(*prot, access_type)) {
 *raddr = eaddr;
 return true;
 }
@@ -403,7 +403,7 @@ bool ppc_hash32_xlate(PowerPCCPU *cpu, vaddr eaddr, 
MMUAccessType access_type,
 if (env->nb_BATs != 0) {
 raddr = ppc_hash32_bat_lookup(cpu, eaddr, access_type, protp, mmu_idx);
 if (raddr != -1) {
-if (prot_for_access_type(access_type) & ~*protp) {
+if (!check_prot_access_type(*protp, access_type)) {
 if (guest_visible) {
 if (access_type == MMU_INST_FETCH) {
 cs->exception_index = POWERPC_EXCP_ISI;
@@ -471,7 +471,7 @@ bool ppc_hash32_xlate(PowerPCCPU *cpu, vaddr eaddr, 
MMUAccessType access_type,
 
 prot = ppc_hash32_pte_prot(mmu_idx, sr, pte);
 
-if (prot_for_access_type(access_type) & ~prot) {
+if (!check_prot_access_type(prot, access_type)) {
 /* Access right violation */
 qemu_log_mask(CPU_LOG_MMU, "PTE access rejected\n");
 if (guest_visible) {
diff --git a/target/ppc/mmu-hash64.c b/target/ppc/mmu-hash64.c
index 0966422a55..d9626f6aab 100644
--- a/target/ppc/mmu-hash64.c
+++ b/target/ppc/mmu-hash64.c
@@ -1097,7 +1097,7 @@ bool ppc_hash64_xlate(PowerPCCPU *cpu, vaddr eaddr, 
MMUAccessType access_type,
 amr_prot = ppc_hash64_amr_prot(cpu, pte);
 prot = exec_prot & pp_prot & amr_prot;
 
-need_prot = prot_for_access_type(access_type);
+need_prot = check_prot_access_type(PAGE_RWX, access_type);
 if (need_prot & ~prot) {
 /* Access right violation */
 qemu_log_mask(CPU_LOG_MMU, "PTE access rejected\n");
diff --git a/target/ppc/mmu-radix64.c b/target/ppc/mmu-radix64.c
index 395ce3b782..2c5ade5cea 100644
--- a/target/ppc/mmu-radix64.c
+++ b/target/ppc/mmu-radix64.c
@@ -209,7 +209,7 @@ static bool ppc_radix64_check_prot(PowerPCCPU *cpu, 
MMUAccessType access_type,
 }
 
 /* Check if requested access type is allowed */
-if (prot_for_access_type(access_type) & ~*prot) {
+if (!check_prot_access_type(*prot, access_type)) {
 /* Page Protected for that Access */
 *fault_cause |= access_type == MMU_INST_FETCH ? SRR1_NOEXEC_GUARD :

[PATCH v7 61/61] target/ppc/mmu_common.c: Remove a local variable

2024-05-12 Thread BALATON Zoltan
In mmu6xx_get_physical_address() the cpu variable is only used for
debug logging which is normally disabled. Inline the value and remove
local variable to avoid computing it when not needed.

Signed-off-by: BALATON Zoltan 
---
 target/ppc/mmu_common.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/target/ppc/mmu_common.c b/target/ppc/mmu_common.c
index 51ef59cdf1..5d944ced07 100644
--- a/target/ppc/mmu_common.c
+++ b/target/ppc/mmu_common.c
@@ -263,7 +263,6 @@ static int mmu6xx_get_physical_address(CPUPPCState *env, 
hwaddr *raddr,
hwaddr *hashp, bool *keyp,
MMUAccessType access_type, int type)
 {
-PowerPCCPU *cpu = env_archcpu(env);
 hwaddr hash;
 target_ulong vsid, sr, pgidx, ptem;
 bool key, ds, nx;
@@ -305,7 +304,8 @@ static int mmu6xx_get_physical_address(CPUPPCState *env, 
hwaddr *raddr,
 /* Page address translation */
 qemu_log_mask(CPU_LOG_MMU, "htab_base " HWADDR_FMT_plx " htab_mask "
   HWADDR_FMT_plx " hash " HWADDR_FMT_plx "\n",
-  ppc_hash32_hpt_base(cpu), ppc_hash32_hpt_mask(cpu), 
hash);
+  ppc_hash32_hpt_base(env_archcpu(env)),
+  ppc_hash32_hpt_mask(env_archcpu(env)), hash);
 *hashp = hash;
 
 /* Software TLB search */
-- 
2.30.9




[PATCH v7 57/61] targe/ppc/mmu_common.c: Use defines instead of numeric constants

2024-05-12 Thread BALATON Zoltan
Replace some BAT related constants with defines from mmu-hash32.h

Signed-off-by: BALATON Zoltan 
---
 target/ppc/mmu_common.c | 26 +-
 1 file changed, 13 insertions(+), 13 deletions(-)

diff --git a/target/ppc/mmu_common.c b/target/ppc/mmu_common.c
index fd8767879d..bfd3787e32 100644
--- a/target/ppc/mmu_common.c
+++ b/target/ppc/mmu_common.c
@@ -201,7 +201,7 @@ static inline void bat_size_prot(CPUPPCState *env, 
target_ulong *blp,
 target_ulong bl;
 int pp, valid, prot;
 
-bl = (*BATu & 0x1FFC) << 15;
+bl = (*BATu & BATU32_BL) << 15;
 valid = 0;
 prot = 0;
 if ((!FIELD_EX64(env->msr, MSR, PR) && (*BATu & 0x0002)) ||
@@ -241,19 +241,19 @@ static int get_bat_6xx_tlb(CPUPPCState *env, mmu_ctx_t 
*ctx,
 for (i = 0; i < env->nb_BATs; i++) {
 BATu = [i];
 BATl = [i];
-BEPIu = *BATu & 0xF000;
-BEPIl = *BATu & 0x0FFE;
+BEPIu = *BATu & BATU32_BEPIU;
+BEPIl = *BATu & BATU32_BEPIL;
 bat_size_prot(env, , , , BATu, BATl);
 qemu_log_mask(CPU_LOG_MMU, "%s: %cBAT%d v " TARGET_FMT_lx " BATu "
   TARGET_FMT_lx " BATl " TARGET_FMT_lx "\n", __func__,
   ifetch ? 'I' : 'D', i, eaddr, *BATu, *BATl);
-if ((eaddr & 0xF000) == BEPIu &&
-((eaddr & 0x0FFE) & ~bl) == BEPIl) {
+if ((eaddr & BATU32_BEPIU) == BEPIu &&
+((eaddr & BATU32_BEPIL) & ~bl) == BEPIl) {
 /* BAT matches */
 if (valid != 0) {
 /* Get physical address */
-ctx->raddr = (*BATl & 0xF000) |
-((eaddr & 0x0FFE & bl) | (*BATl & 0x0FFE)) |
+ctx->raddr = (*BATl & BATU32_BEPIU) |
+((eaddr & BATU32_BEPIL & bl) | (*BATl & BATU32_BEPIL)) |
 (eaddr & 0x0001F000);
 /* Compute access rights */
 ctx->prot = prot;
@@ -277,9 +277,9 @@ static int get_bat_6xx_tlb(CPUPPCState *env, mmu_ctx_t *ctx,
 for (i = 0; i < 4; i++) {
 BATu = [i];
 BATl = [i];
-BEPIu = *BATu & 0xF000;
-BEPIl = *BATu & 0x0FFE;
-bl = (*BATu & 0x1FFC) << 15;
+BEPIu = *BATu & BATU32_BEPIU;
+BEPIl = *BATu & BATU32_BEPIL;
+bl = (*BATu & BATU32_BL) << 15;
 qemu_log_mask(CPU_LOG_MMU, "%s: %cBAT%d v " TARGET_FMT_lx
   " BATu " TARGET_FMT_lx " BATl " TARGET_FMT_lx
   "\n\t" TARGET_FMT_lx " " TARGET_FMT_lx " "
@@ -520,9 +520,9 @@ static void mmu6xx_dump_BATs(CPUPPCState *env, int type)
 for (i = 0; i < env->nb_BATs; i++) {
 BATu = [i];
 BATl = [i];
-BEPIu = *BATu & 0xF000;
-BEPIl = *BATu & 0x0FFE;
-bl = (*BATu & 0x1FFC) << 15;
+BEPIu = *BATu & BATU32_BEPIU;
+BEPIl = *BATu & BATU32_BEPIL;
+bl = (*BATu & BATU32_BL) << 15;
 qemu_printf("%s BAT%d BATu " TARGET_FMT_lx
 " BATl " TARGET_FMT_lx "\n\t" TARGET_FMT_lx " "
 TARGET_FMT_lx " " TARGET_FMT_lx "\n",
-- 
2.30.9




[PATCH v7 03/61] target/ppc/mmu_common.c: Move calculation of a value closer to its usage

2024-05-12 Thread BALATON Zoltan
In mmubooke_check_tlb() and mmubooke206_check_tlb() prot2 is
calculated first but only used after an unrelated check that can
return before tha value is used. Move the calculation after the check,
closer to where it is used, to keep them together and avoid computing
it when not needed.

Signed-off-by: BALATON Zoltan 
Reviwed-by: Nicholas Piggin 
---
 target/ppc/mmu_common.c | 36 +---
 1 file changed, 17 insertions(+), 19 deletions(-)

diff --git a/target/ppc/mmu_common.c b/target/ppc/mmu_common.c
index 4fde7fd3bf..f79e390306 100644
--- a/target/ppc/mmu_common.c
+++ b/target/ppc/mmu_common.c
@@ -635,12 +635,6 @@ static int mmubooke_check_tlb(CPUPPCState *env, 
ppcemb_tlb_t *tlb,
 return -1;
 }
 
-if (FIELD_EX64(env->msr, MSR, PR)) {
-prot2 = tlb->prot & 0xF;
-} else {
-prot2 = (tlb->prot >> 4) & 0xF;
-}
-
 /* Check the address space */
 if ((access_type == MMU_INST_FETCH ?
 FIELD_EX64(env->msr, MSR, IR) :
@@ -649,6 +643,11 @@ static int mmubooke_check_tlb(CPUPPCState *env, 
ppcemb_tlb_t *tlb,
 return -1;
 }
 
+if (FIELD_EX64(env->msr, MSR, PR)) {
+prot2 = tlb->prot & 0xF;
+} else {
+prot2 = (tlb->prot >> 4) & 0xF;
+}
 *prot = prot2;
 if (prot2 & prot_for_access_type(access_type)) {
 qemu_log_mask(CPU_LOG_MMU, "%s: good TLB!\n", __func__);
@@ -830,6 +829,18 @@ static int mmubooke206_check_tlb(CPUPPCState *env, 
ppcmas_tlb_t *tlb,
 
 found_tlb:
 
+/* Check the address space and permissions */
+if (access_type == MMU_INST_FETCH) {
+/* There is no way to fetch code using epid load */
+assert(!use_epid);
+as = FIELD_EX64(env->msr, MSR, IR);
+}
+
+if (as != ((tlb->mas1 & MAS1_TS) >> MAS1_TS_SHIFT)) {
+qemu_log_mask(CPU_LOG_MMU, "%s: AS doesn't match\n", __func__);
+return -1;
+}
+
 if (pr) {
 if (tlb->mas7_3 & MAS3_UR) {
 prot2 |= PAGE_READ;
@@ -851,19 +862,6 @@ found_tlb:
 prot2 |= PAGE_EXEC;
 }
 }
-
-/* Check the address space and permissions */
-if (access_type == MMU_INST_FETCH) {
-/* There is no way to fetch code using epid load */
-assert(!use_epid);
-as = FIELD_EX64(env->msr, MSR, IR);
-}
-
-if (as != ((tlb->mas1 & MAS1_TS) >> MAS1_TS_SHIFT)) {
-qemu_log_mask(CPU_LOG_MMU, "%s: AS doesn't match\n", __func__);
-return -1;
-}
-
 *prot = prot2;
 if (prot2 & prot_for_access_type(access_type)) {
 qemu_log_mask(CPU_LOG_MMU, "%s: good TLB!\n", __func__);
-- 
2.30.9




[PATCH v7 58/61] target/ppc: Remove bat_size_prot()

2024-05-12 Thread BALATON Zoltan
There is already a hash32_bat_prot() function that does most if this
and the rest can be inlined. Export hash32_bat_prot() and rename it to
ppc_hash32_bat_prot() to match other functions and use it in
get_bat_6xx_tlb().

Signed-off-by: BALATON Zoltan 
---
 target/ppc/mmu-hash32.c | 18 +-
 target/ppc/mmu-hash32.h | 14 +++
 target/ppc/mmu_common.c | 52 ++---
 3 files changed, 27 insertions(+), 57 deletions(-)

diff --git a/target/ppc/mmu-hash32.c b/target/ppc/mmu-hash32.c
index 9de42713b3..cc19041cc2 100644
--- a/target/ppc/mmu-hash32.c
+++ b/target/ppc/mmu-hash32.c
@@ -48,22 +48,6 @@ static target_ulong hash32_bat_size(int mmu_idx,
 return BATU32_BEPI & ~((batu & BATU32_BL) << 15);
 }
 
-static int hash32_bat_prot(PowerPCCPU *cpu,
-   target_ulong batu, target_ulong batl)
-{
-int pp, prot;
-
-prot = 0;
-pp = batl & BATL32_PP;
-if (pp != 0) {
-prot = PAGE_READ | PAGE_EXEC;
-if (pp == 0x2) {
-prot |= PAGE_WRITE;
-}
-}
-return prot;
-}
-
 static hwaddr ppc_hash32_bat_lookup(PowerPCCPU *cpu, target_ulong ea,
 MMUAccessType access_type, int *prot,
 int mmu_idx)
@@ -95,7 +79,7 @@ static hwaddr ppc_hash32_bat_lookup(PowerPCCPU *cpu, 
target_ulong ea,
 if (mask && ((ea & mask) == (batu & BATU32_BEPI))) {
 hwaddr raddr = (batl & mask) | (ea & ~mask);
 
-*prot = hash32_bat_prot(cpu, batu, batl);
+*prot = ppc_hash32_bat_prot(batu, batl);
 
 return raddr & TARGET_PAGE_MASK;
 }
diff --git a/target/ppc/mmu-hash32.h b/target/ppc/mmu-hash32.h
index 6e5796d7cb..f86ef8dd82 100644
--- a/target/ppc/mmu-hash32.h
+++ b/target/ppc/mmu-hash32.h
@@ -143,6 +143,20 @@ static inline int ppc_hash32_pp_prot(bool key, int pp, 
bool nx)
 return nx ? prot : prot | PAGE_EXEC;
 }
 
+static inline int ppc_hash32_bat_prot(target_ulong batu, target_ulong batl)
+{
+int prot = 0;
+int pp = batl & BATL32_PP;
+
+if (pp) {
+prot = PAGE_READ | PAGE_EXEC;
+if (pp == 0x2) {
+prot |= PAGE_WRITE;
+}
+}
+return prot;
+}
+
 typedef struct {
 uint32_t pte0, pte1;
 } ppc_hash_pte32_t;
diff --git a/target/ppc/mmu_common.c b/target/ppc/mmu_common.c
index bfd3787e32..ba54c40048 100644
--- a/target/ppc/mmu_common.c
+++ b/target/ppc/mmu_common.c
@@ -193,40 +193,13 @@ static int ppc6xx_tlb_check(CPUPPCState *env, hwaddr 
*raddr, int *prot,
 return ret;
 }
 
-/* Perform BAT hit & translation */
-static inline void bat_size_prot(CPUPPCState *env, target_ulong *blp,
- int *validp, int *protp, target_ulong *BATu,
- target_ulong *BATl)
-{
-target_ulong bl;
-int pp, valid, prot;
-
-bl = (*BATu & BATU32_BL) << 15;
-valid = 0;
-prot = 0;
-if ((!FIELD_EX64(env->msr, MSR, PR) && (*BATu & 0x0002)) ||
-(FIELD_EX64(env->msr, MSR, PR) && (*BATu & 0x0001))) {
-valid = 1;
-pp = *BATl & 0x0003;
-if (pp != 0) {
-prot = PAGE_READ | PAGE_EXEC;
-if (pp == 0x2) {
-prot |= PAGE_WRITE;
-}
-}
-}
-*blp = bl;
-*validp = valid;
-*protp = prot;
-}
-
 static int get_bat_6xx_tlb(CPUPPCState *env, mmu_ctx_t *ctx,
-   target_ulong eaddr, MMUAccessType access_type)
+   target_ulong eaddr, MMUAccessType access_type,
+   bool pr)
 {
 target_ulong *BATlt, *BATut, *BATu, *BATl;
 target_ulong BEPIl, BEPIu, bl;
-int i, valid, prot;
-int ret = -1;
+int i, ret = -1;
 bool ifetch = access_type == MMU_INST_FETCH;
 
 qemu_log_mask(CPU_LOG_MMU, "%s: %cBAT v " TARGET_FMT_lx "\n", __func__,
@@ -243,20 +216,19 @@ static int get_bat_6xx_tlb(CPUPPCState *env, mmu_ctx_t 
*ctx,
 BATl = [i];
 BEPIu = *BATu & BATU32_BEPIU;
 BEPIl = *BATu & BATU32_BEPIL;
-bat_size_prot(env, , , , BATu, BATl);
 qemu_log_mask(CPU_LOG_MMU, "%s: %cBAT%d v " TARGET_FMT_lx " BATu "
   TARGET_FMT_lx " BATl " TARGET_FMT_lx "\n", __func__,
   ifetch ? 'I' : 'D', i, eaddr, *BATu, *BATl);
-if ((eaddr & BATU32_BEPIU) == BEPIu &&
-((eaddr & BATU32_BEPIL) & ~bl) == BEPIl) {
-/* BAT matches */
-if (valid != 0) {
+bl = (*BATu & BATU32_BL) << 15;
+if ((!pr && (*BATu & BATU32_VS)) || (pr && (*BATu & BATU32_VP))) {
+if ((eaddr & BATU32_BEPIU) == BEPIu &&
+((eaddr & BATU32_BEPIL) & ~bl) == BEPIl) {
 /* Get physical address */
 ctx->raddr = (*BATl & BATU32_BEPIU) |
 ((eaddr & BATU32_BEPIL & bl) | (*BATl & BATU32_BEPIL)) |
 (eaddr & 0x0001F000);
 /* Compute 

[PATCH v7 16/61] target/ppc/mmu_common.c: Replace hard coded constants in ppc_jumbo_xlate()

2024-05-12 Thread BALATON Zoltan
The "2" in booke206_update_mas_tlb_miss() call corresponds to
MMU_INST_FETCH which is the value of access_type in this branch;
mmubooke206_esr() only checks for MMU_DATA_STORE and it's called from
code access so using MMU_DATA_LOAD here seems wrong so replace it with
access_type here as well that yields the same result. This also makes
these calls the same as the data access branch further down.

Signed-off-by: BALATON Zoltan 
Reviewed-by: Nicholas Piggin 
---
 target/ppc/mmu_common.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/target/ppc/mmu_common.c b/target/ppc/mmu_common.c
index f40481b4b1..6570b280ca 100644
--- a/target/ppc/mmu_common.c
+++ b/target/ppc/mmu_common.c
@@ -1287,13 +1287,13 @@ static bool ppc_jumbo_xlate(PowerPCCPU *cpu, vaddr 
eaddr,
 env->spr[SPR_40x_ESR] = 0x;
 break;
 case POWERPC_MMU_BOOKE206:
-booke206_update_mas_tlb_miss(env, eaddr, 2, mmu_idx);
+booke206_update_mas_tlb_miss(env, eaddr, access_type, mmu_idx);
 /* fall through */
 case POWERPC_MMU_BOOKE:
 cs->exception_index = POWERPC_EXCP_ITLB;
 env->error_code = 0;
 env->spr[SPR_BOOKE_DEAR] = eaddr;
-env->spr[SPR_BOOKE_ESR] = mmubooke206_esr(mmu_idx, 
MMU_DATA_LOAD);
+env->spr[SPR_BOOKE_ESR] = mmubooke206_esr(mmu_idx, 
access_type);
 break;
 case POWERPC_MMU_REAL:
 cpu_abort(cs, "PowerPC in real mode should never raise "
-- 
2.30.9




[PATCH v7 51/61] target/ppc: Add function to get protection key for hash32 MMU

2024-05-12 Thread BALATON Zoltan
Add a function to get key bit from SR and use it instead of open coded
version.

Signed-off-by: BALATON Zoltan 
---
 target/ppc/mmu-hash32.c | 9 ++---
 target/ppc/mmu-hash32.h | 5 +
 target/ppc/mmu_common.c | 3 +--
 3 files changed, 12 insertions(+), 5 deletions(-)

diff --git a/target/ppc/mmu-hash32.c b/target/ppc/mmu-hash32.c
index d5f2057eb1..8e5e83f46a 100644
--- a/target/ppc/mmu-hash32.c
+++ b/target/ppc/mmu-hash32.c
@@ -42,7 +42,7 @@ static int ppc_hash32_pte_prot(int mmu_idx,
 {
 unsigned pp, key;
 
-key = !!(mmuidx_pr(mmu_idx) ? (sr & SR32_KP) : (sr & SR32_KS));
+key = ppc_hash32_key(mmuidx_pr(mmu_idx), sr);
 pp = pte.pte1 & HPTE32_R_PP;
 
 return ppc_hash32_pp_prot(key, pp, !!(sr & SR32_NX));
@@ -145,7 +145,6 @@ static bool ppc_hash32_direct_store(PowerPCCPU *cpu, 
target_ulong sr,
 {
 CPUState *cs = CPU(cpu);
 CPUPPCState *env = >env;
-int key = !!(mmuidx_pr(mmu_idx) ? (sr & SR32_KP) : (sr & SR32_KS));
 
 qemu_log_mask(CPU_LOG_MMU, "direct store...\n");
 
@@ -206,7 +205,11 @@ static bool ppc_hash32_direct_store(PowerPCCPU *cpu, 
target_ulong sr,
 cpu_abort(cs, "ERROR: insn should not need address translation\n");
 }
 
-*prot = key ? PAGE_READ | PAGE_WRITE : PAGE_READ;
+if (ppc_hash32_key(mmuidx_pr(mmu_idx), sr)) {
+*prot = PAGE_READ | PAGE_WRITE;
+} else {
+*prot = PAGE_READ;
+}
 if (check_prot_access_type(*prot, access_type)) {
 *raddr = eaddr;
 return true;
diff --git a/target/ppc/mmu-hash32.h b/target/ppc/mmu-hash32.h
index bf99161858..6e5796d7cb 100644
--- a/target/ppc/mmu-hash32.h
+++ b/target/ppc/mmu-hash32.h
@@ -102,6 +102,11 @@ static inline void ppc_hash32_store_hpte1(PowerPCCPU *cpu,
 stl_phys(CPU(cpu)->as, base + pte_offset + HASH_PTE_SIZE_32 / 2, pte1);
 }
 
+static inline bool ppc_hash32_key(bool pr, target_ulong sr)
+{
+return pr ? (sr & SR32_KP) : (sr & SR32_KS);
+}
+
 static inline int ppc_hash32_pp_prot(bool key, int pp, bool nx)
 {
 int prot;
diff --git a/target/ppc/mmu_common.c b/target/ppc/mmu_common.c
index f09f7417c2..3d028a2008 100644
--- a/target/ppc/mmu_common.c
+++ b/target/ppc/mmu_common.c
@@ -310,8 +310,7 @@ static int mmu6xx_get_physical_address(CPUPPCState *env, 
mmu_ctx_t *ctx,
 pr = FIELD_EX64(env->msr, MSR, PR);
 
 sr = env->sr[eaddr >> 28];
-ctx->key = (((sr & 0x2000) && pr) ||
-((sr & 0x4000) && !pr)) ? 1 : 0;
+ctx->key = ppc_hash32_key(pr, sr);
 ds = sr & SR32_T;
 nx = sr & SR32_NX;
 vsid = sr & SR32_VSID;
-- 
2.30.9




[PATCH v7 52/61] target/ppc/mmu-hash32.c: Inline and remove ppc_hash32_pte_prot()

2024-05-12 Thread BALATON Zoltan
This is used only once and can be inlined.

Signed-off-by: BALATON Zoltan 
---
 target/ppc/mmu-hash32.c | 19 ---
 1 file changed, 4 insertions(+), 15 deletions(-)

diff --git a/target/ppc/mmu-hash32.c b/target/ppc/mmu-hash32.c
index 8e5e83f46a..9de42713b3 100644
--- a/target/ppc/mmu-hash32.c
+++ b/target/ppc/mmu-hash32.c
@@ -37,17 +37,6 @@
 #  define LOG_BATS(...) do { } while (0)
 #endif
 
-static int ppc_hash32_pte_prot(int mmu_idx,
-   target_ulong sr, ppc_hash_pte32_t pte)
-{
-unsigned pp, key;
-
-key = ppc_hash32_key(mmuidx_pr(mmu_idx), sr);
-pp = pte.pte1 & HPTE32_R_PP;
-
-return ppc_hash32_pp_prot(key, pp, !!(sr & SR32_NX));
-}
-
 static target_ulong hash32_bat_size(int mmu_idx,
 target_ulong batu, target_ulong batl)
 {
@@ -341,10 +330,10 @@ bool ppc_hash32_xlate(PowerPCCPU *cpu, vaddr eaddr, 
MMUAccessType access_type,
 CPUState *cs = CPU(cpu);
 CPUPPCState *env = >env;
 target_ulong sr;
-hwaddr pte_offset;
+hwaddr pte_offset, raddr;
 ppc_hash_pte32_t pte;
+bool key;
 int prot;
-hwaddr raddr;
 
 /* There are no hash32 large pages. */
 *psizep = TARGET_PAGE_BITS;
@@ -426,8 +415,8 @@ bool ppc_hash32_xlate(PowerPCCPU *cpu, vaddr eaddr, 
MMUAccessType access_type,
 "found PTE at offset %08" HWADDR_PRIx "\n", pte_offset);
 
 /* 7. Check access permissions */
-
-prot = ppc_hash32_pte_prot(mmu_idx, sr, pte);
+key = ppc_hash32_key(mmuidx_pr(mmu_idx), sr);
+prot = ppc_hash32_pp_prot(key, pte.pte1 & HPTE32_R_PP, sr & SR32_NX);
 
 if (!check_prot_access_type(prot, access_type)) {
 /* Access right violation */
-- 
2.30.9




[PATCH v7 54/61] target/ppc/mmu_common.c: Remove key field from mmu_ctx_t

2024-05-12 Thread BALATON Zoltan
Pass it as a function argument and remove it from mmu_ctx_t.

Signed-off-by: BALATON Zoltan 
---
 target/ppc/mmu_common.c | 26 ++
 1 file changed, 14 insertions(+), 12 deletions(-)

diff --git a/target/ppc/mmu_common.c b/target/ppc/mmu_common.c
index ccc1c76a06..331e00b71c 100644
--- a/target/ppc/mmu_common.c
+++ b/target/ppc/mmu_common.c
@@ -41,7 +41,6 @@
 typedef struct {
 hwaddr raddr;  /* Real address */
 int prot;  /* Protection bits  */
-int key;   /* Access key   */
 } mmu_ctx_t;
 
 void ppc_store_sdr1(CPUPPCState *env, target_ulong value)
@@ -95,7 +94,7 @@ int ppc6xx_tlb_getnum(CPUPPCState *env, target_ulong eaddr,
 static int ppc6xx_tlb_check(CPUPPCState *env,
 mmu_ctx_t *ctx, target_ulong eaddr,
 MMUAccessType access_type, target_ulong ptem,
-bool nx)
+bool key, bool nx)
 {
 ppc6xx_tlb_t *tlb;
 target_ulong *pte1p;
@@ -140,7 +139,7 @@ static int ppc6xx_tlb_check(CPUPPCState *env,
 /* Keep the matching PTE information */
 best = nr;
 ctx->raddr = tlb->pte1;
-ctx->prot = ppc_hash32_pp_prot(ctx->key, tlb->pte1 & HPTE32_R_PP, nx);
+ctx->prot = ppc_hash32_pp_prot(key, tlb->pte1 & HPTE32_R_PP, nx);
 if (check_prot_access_type(ctx->prot, access_type)) {
 qemu_log_mask(CPU_LOG_MMU, "PTE access granted !\n");
 ret = 0;
@@ -295,13 +294,14 @@ static int get_bat_6xx_tlb(CPUPPCState *env, mmu_ctx_t 
*ctx,
 }
 
 static int mmu6xx_get_physical_address(CPUPPCState *env, mmu_ctx_t *ctx,
-   target_ulong eaddr, hwaddr *hashp,
+   target_ulong eaddr,
+   hwaddr *hashp, bool *keyp,
MMUAccessType access_type, int type)
 {
 PowerPCCPU *cpu = env_archcpu(env);
 hwaddr hash;
 target_ulong vsid, sr, pgidx, ptem;
-bool pr, ds, nx;
+bool key, pr, ds, nx;
 
 /* First try to find a BAT entry if there are any */
 if (env->nb_BATs && get_bat_6xx_tlb(env, ctx, eaddr, access_type) == 0) {
@@ -312,7 +312,8 @@ static int mmu6xx_get_physical_address(CPUPPCState *env, 
mmu_ctx_t *ctx,
 pr = FIELD_EX64(env->msr, MSR, PR);
 
 sr = env->sr[eaddr >> 28];
-ctx->key = ppc_hash32_key(pr, sr);
+key = ppc_hash32_key(pr, sr);
+*keyp = key;
 ds = sr & SR32_T;
 nx = sr & SR32_NX;
 vsid = sr & SR32_VSID;
@@ -329,7 +330,7 @@ static int mmu6xx_get_physical_address(CPUPPCState *env, 
mmu_ctx_t *ctx,
 ptem = (vsid << 7) | (pgidx >> 10); /* Virtual segment ID | API */
 
 qemu_log_mask(CPU_LOG_MMU, "pte segment: key=%d ds %d nx %d vsid "
-  TARGET_FMT_lx "\n", ctx->key, ds, nx, vsid);
+  TARGET_FMT_lx "\n", key, ds, nx, vsid);
 if (!ds) {
 /* Check if instruction fetch is allowed, if needed */
 if (type == ACCESS_CODE && nx) {
@@ -343,7 +344,7 @@ static int mmu6xx_get_physical_address(CPUPPCState *env, 
mmu_ctx_t *ctx,
 *hashp = hash;
 
 /* Software TLB search */
-return ppc6xx_tlb_check(env, ctx, eaddr, access_type, ptem, nx);
+return ppc6xx_tlb_check(env, ctx, eaddr, access_type, ptem, key, nx);
 }
 
 /* Direct-store segment : absolutely *BUGGY* for now */
@@ -367,8 +368,8 @@ static int mmu6xx_get_physical_address(CPUPPCState *env, 
mmu_ctx_t *ctx,
 case ACCESS_EXT: /* eciwx or ecowx */
 return -4;
 }
-if ((access_type == MMU_DATA_STORE || ctx->key != 1) &&
-(access_type == MMU_DATA_LOAD || ctx->key != 0)) {
+if ((access_type == MMU_DATA_STORE || !key) &&
+(access_type == MMU_DATA_LOAD || key)) {
 ctx->raddr = eaddr;
 return 2;
 }
@@ -709,6 +710,7 @@ static bool ppc_6xx_xlate(PowerPCCPU *cpu, vaddr eaddr,
 CPUPPCState *env = >env;
 mmu_ctx_t ctx;
 hwaddr hash = 0; /* init to 0 to avoid used uninit warning */
+bool key;
 int type, ret;
 
 if (ppc_real_mode_xlate(cpu, eaddr, access_type, raddrp, psizep, protp)) {
@@ -726,7 +728,7 @@ static bool ppc_6xx_xlate(PowerPCCPU *cpu, vaddr eaddr,
 }
 
 ctx.prot = 0;
-ret = mmu6xx_get_physical_address(env, , eaddr, ,
+ret = mmu6xx_get_physical_address(env, , eaddr, , ,
   access_type, type);
 if (ret == 0) {
 *raddrp = ctx.raddr;
@@ -778,7 +780,7 @@ static bool ppc_6xx_xlate(PowerPCCPU *cpu, vaddr eaddr,
 env->spr[SPR_DMISS] = eaddr;
 env->spr[SPR_DCMP] |= 0x8000;
 tlb_miss:
-env->error_code |= ctx.key << 19;
+env->error_code |= key << 19;
 env->spr[SPR_HASH1] = ppc_hash32_hpt_base(cpu) +
   get_pteg_offset32(cpu, hash);
 env->spr[SPR_HASH2] = ppc_hash32_hpt_base(cpu) +
-- 
2.30.9



[PATCH v7 60/61] target/ppc/mmu_common.c: Remove mmu_ctx_t

2024-05-12 Thread BALATON Zoltan
Completely get rid of mmu_ctx_t after converting the remaining
functions to pass raddr and prot without the context struct.

Signed-off-by: BALATON Zoltan 
---
 target/ppc/mmu_common.c | 25 +++--
 1 file changed, 7 insertions(+), 18 deletions(-)

diff --git a/target/ppc/mmu_common.c b/target/ppc/mmu_common.c
index 6d588b6795..51ef59cdf1 100644
--- a/target/ppc/mmu_common.c
+++ b/target/ppc/mmu_common.c
@@ -37,12 +37,6 @@
 
 /* #define DUMP_PAGE_TABLES */
 
-/* Context used internally during MMU translations */
-typedef struct {
-hwaddr raddr;  /* Real address */
-int prot;  /* Protection bits  */
-} mmu_ctx_t;
-
 void ppc_store_sdr1(CPUPPCState *env, target_ulong value)
 {
 PowerPCCPU *cpu = env_archcpu(env);
@@ -264,8 +258,8 @@ static int get_bat_6xx_tlb(CPUPPCState *env, hwaddr *raddr, 
int *prot,
 return ret;
 }
 
-static int mmu6xx_get_physical_address(CPUPPCState *env, mmu_ctx_t *ctx,
-   target_ulong eaddr,
+static int mmu6xx_get_physical_address(CPUPPCState *env, hwaddr *raddr,
+   int *prot, target_ulong eaddr,
hwaddr *hashp, bool *keyp,
MMUAccessType access_type, int type)
 {
@@ -277,8 +271,7 @@ static int mmu6xx_get_physical_address(CPUPPCState *env, 
mmu_ctx_t *ctx,
 
 /* First try to find a BAT entry if there are any */
 if (env->nb_BATs &&
-get_bat_6xx_tlb(env, >raddr, >prot, eaddr,
-access_type, pr) == 0) {
+get_bat_6xx_tlb(env, raddr, prot, eaddr, access_type, pr) == 0) {
 return 0;
 }
 
@@ -316,7 +309,7 @@ static int mmu6xx_get_physical_address(CPUPPCState *env, 
mmu_ctx_t *ctx,
 *hashp = hash;
 
 /* Software TLB search */
-return ppc6xx_tlb_check(env, >raddr, >prot, eaddr,
+return ppc6xx_tlb_check(env, raddr, prot, eaddr,
 access_type, ptem, key, nx);
 }
 
@@ -333,7 +326,7 @@ static int mmu6xx_get_physical_address(CPUPPCState *env, 
mmu_ctx_t *ctx,
  * Should make the instruction do no-op.  As it already do
  * no-op, it's quite easy :-)
  */
-ctx->raddr = eaddr;
+*raddr = eaddr;
 return 0;
 case ACCESS_CODE: /* No code fetch is allowed in direct-store areas */
 case ACCESS_FLOAT: /* Floating point load/store */
@@ -343,7 +336,7 @@ static int mmu6xx_get_physical_address(CPUPPCState *env, 
mmu_ctx_t *ctx,
 }
 if ((access_type == MMU_DATA_STORE || !key) &&
 (access_type == MMU_DATA_LOAD || key)) {
-ctx->raddr = eaddr;
+*raddr = eaddr;
 return 2;
 }
 return -2;
@@ -681,7 +674,6 @@ static bool ppc_6xx_xlate(PowerPCCPU *cpu, vaddr eaddr,
 {
 CPUState *cs = CPU(cpu);
 CPUPPCState *env = >env;
-mmu_ctx_t ctx;
 hwaddr hash = 0; /* init to 0 to avoid used uninit warning */
 bool key;
 int type, ret;
@@ -700,12 +692,9 @@ static bool ppc_6xx_xlate(PowerPCCPU *cpu, vaddr eaddr,
 type = ACCESS_INT;
 }
 
-ctx.prot = 0;
-ret = mmu6xx_get_physical_address(env, , eaddr, , ,
+ret = mmu6xx_get_physical_address(env, raddrp, protp, eaddr, , ,
   access_type, type);
 if (ret == 0) {
-*raddrp = ctx.raddr;
-*protp = ctx.prot;
 *psizep = TARGET_PAGE_BITS;
 return true;
 } else if (!guest_visible) {
-- 
2.30.9




[PATCH v7 23/61] target/ppc/mmu_common.c: Simplify ppc_booke_xlate() part 2

2024-05-12 Thread BALATON Zoltan
Merge the code fetch and data access cases in a common switch.

Signed-off-by: BALATON Zoltan 
Reviewed-by: Nicholas Piggin 
---
 target/ppc/mmu_common.c | 52 -
 1 file changed, 20 insertions(+), 32 deletions(-)

diff --git a/target/ppc/mmu_common.c b/target/ppc/mmu_common.c
index 611092966b..8599106f75 100644
--- a/target/ppc/mmu_common.c
+++ b/target/ppc/mmu_common.c
@@ -1221,45 +1221,33 @@ static bool ppc_booke_xlate(PowerPCCPU *cpu, vaddr 
eaddr,
 
 log_cpu_state_mask(CPU_LOG_MMU, cs, 0);
 env->error_code = 0;
-if (ret == -1) {
+switch (ret) {
+case -1:
+/* No matches in page tables or TLB */
 if (env->mmu_model == POWERPC_MMU_BOOKE206) {
 booke206_update_mas_tlb_miss(env, eaddr, access_type, mmu_idx);
 }
-}
-if (access_type == MMU_INST_FETCH) {
-switch (ret) {
-case -1:
-/* No matches in page tables or TLB */
-cs->exception_index = POWERPC_EXCP_ITLB;
-env->spr[SPR_BOOKE_DEAR] = eaddr;
-env->spr[SPR_BOOKE_ESR] = mmubooke206_esr(mmu_idx, access_type);
-break;
-case -2:
-/* Access rights violation */
-cs->exception_index = POWERPC_EXCP_ISI;
-break;
-case -3:
-/* No execute protection violation */
-cs->exception_index = POWERPC_EXCP_ISI;
-env->spr[SPR_BOOKE_ESR] = 0;
-break;
-}
-} else {
-switch (ret) {
-case -1:
-/* No matches in page tables or TLB */
-cs->exception_index = POWERPC_EXCP_DTLB;
-env->spr[SPR_BOOKE_DEAR] = eaddr;
-env->spr[SPR_BOOKE_ESR] = mmubooke206_esr(mmu_idx, access_type);
-break;
-case -2:
-/* Access rights violation */
-cs->exception_index = POWERPC_EXCP_DSI;
+cs->exception_index = (access_type == MMU_INST_FETCH) ?
+  POWERPC_EXCP_ITLB : POWERPC_EXCP_DTLB;
+env->spr[SPR_BOOKE_DEAR] = eaddr;
+env->spr[SPR_BOOKE_ESR] = mmubooke206_esr(mmu_idx, access_type);
+break;
+case -2:
+/* Access rights violation */
+cs->exception_index = (access_type == MMU_INST_FETCH) ?
+  POWERPC_EXCP_ISI : POWERPC_EXCP_DSI;
+if (access_type != MMU_INST_FETCH) {
 env->spr[SPR_BOOKE_DEAR] = eaddr;
 env->spr[SPR_BOOKE_ESR] = mmubooke206_esr(mmu_idx, access_type);
-break;
 }
+break;
+case -3:
+/* No execute protection violation */
+cs->exception_index = POWERPC_EXCP_ISI;
+env->spr[SPR_BOOKE_ESR] = 0;
+break;
 }
+
 return false;
 }
 
-- 
2.30.9




[PATCH v7 50/61] target/ppc/mmu_common.c: Remove ptem field from mmu_ctx_t

2024-05-12 Thread BALATON Zoltan
Instead of passing around ptem in context use it once in the same
function so it can be removed from mmu_ctx_t.

Signed-off-by: BALATON Zoltan 
---
 target/ppc/mmu_common.c | 23 ++-
 1 file changed, 14 insertions(+), 9 deletions(-)

diff --git a/target/ppc/mmu_common.c b/target/ppc/mmu_common.c
index a4bb8c8c3e..f09f7417c2 100644
--- a/target/ppc/mmu_common.c
+++ b/target/ppc/mmu_common.c
@@ -41,7 +41,6 @@
 typedef struct {
 hwaddr raddr;  /* Real address */
 int prot;  /* Protection bits  */
-target_ulong ptem; /* Virtual segment ID | API */
 int key;   /* Access key   */
 } mmu_ctx_t;
 
@@ -95,16 +94,18 @@ int ppc6xx_tlb_getnum(CPUPPCState *env, target_ulong eaddr,
 
 static int ppc6xx_tlb_check(CPUPPCState *env,
 mmu_ctx_t *ctx, target_ulong eaddr,
-MMUAccessType access_type, bool nx)
+MMUAccessType access_type, target_ulong ptem,
+bool nx)
 {
 ppc6xx_tlb_t *tlb;
 target_ulong *pte1p;
 int nr, best, way, ret;
+bool is_code = (access_type == MMU_INST_FETCH);
 
 best = -1;
 ret = -1; /* No TLB found */
 for (way = 0; way < env->nb_ways; way++) {
-nr = ppc6xx_tlb_getnum(env, eaddr, way, access_type == MMU_INST_FETCH);
+nr = ppc6xx_tlb_getnum(env, eaddr, way, is_code);
 tlb = >tlb.tlb6[nr];
 /* This test "emulates" the PTE index match for hardware TLBs */
 if ((eaddr & TARGET_PAGE_MASK) != tlb->EPN) {
@@ -124,7 +125,7 @@ static int ppc6xx_tlb_check(CPUPPCState *env,
   access_type == MMU_INST_FETCH ? 'I' : 'D');
 /* Check validity and table match */
 if (!pte_is_valid(tlb->pte0) || ((tlb->pte0 >> 6) & 1) != 0 ||
-(tlb->pte0 & PTE_PTEM_MASK) != ctx->ptem) {
+(tlb->pte0 & PTE_PTEM_MASK) != ptem) {
 continue;
 }
 /* all matches should have equal RPN, WIMG & PP */
@@ -164,6 +165,10 @@ static int ppc6xx_tlb_check(CPUPPCState *env,
 }
 }
 }
+if (ret == -1) {
+int r = is_code ? SPR_ICMP : SPR_DCMP;
+env->spr[r] = ptem;
+}
 #if defined(DUMP_PAGE_TABLES)
 if (qemu_loglevel_mask(CPU_LOG_MMU)) {
 CPUState *cs = env_cpu(env);
@@ -293,7 +298,7 @@ static int mmu6xx_get_physical_address(CPUPPCState *env, 
mmu_ctx_t *ctx,
 {
 PowerPCCPU *cpu = env_archcpu(env);
 hwaddr hash;
-target_ulong vsid, sr, pgidx;
+target_ulong vsid, sr, pgidx, ptem;
 bool pr, ds, nx;
 
 /* First try to find a BAT entry if there are any */
@@ -320,7 +325,7 @@ static int mmu6xx_get_physical_address(CPUPPCState *env, 
mmu_ctx_t *ctx,
   access_type == MMU_DATA_STORE, type);
 pgidx = (eaddr & ~SEGMENT_MASK_256M) >> TARGET_PAGE_BITS;
 hash = vsid ^ pgidx;
-ctx->ptem = (vsid << 7) | (pgidx >> 10);
+ptem = (vsid << 7) | (pgidx >> 10); /* Virtual segment ID | API */
 
 qemu_log_mask(CPU_LOG_MMU, "pte segment: key=%d ds %d nx %d vsid "
   TARGET_FMT_lx "\n", ctx->key, ds, nx, vsid);
@@ -339,7 +344,7 @@ static int mmu6xx_get_physical_address(CPUPPCState *env, 
mmu_ctx_t *ctx,
 /* Initialize real address with an invalid value */
 ctx->raddr = (hwaddr)-1ULL;
 /* Software TLB search */
-return ppc6xx_tlb_check(env, ctx, eaddr, access_type, nx);
+return ppc6xx_tlb_check(env, ctx, eaddr, access_type, ptem, nx);
 }
 
 /* Direct-store segment : absolutely *BUGGY* for now */
@@ -741,7 +746,7 @@ static bool ppc_6xx_xlate(PowerPCCPU *cpu, vaddr eaddr,
 cs->exception_index = POWERPC_EXCP_IFTLB;
 env->error_code = 1 << 18;
 env->spr[SPR_IMISS] = eaddr;
-env->spr[SPR_ICMP] = 0x8000 | ctx.ptem;
+env->spr[SPR_ICMP] |= 0x8000;
 goto tlb_miss;
 case -2:
 /* Access rights violation */
@@ -772,7 +777,7 @@ static bool ppc_6xx_xlate(PowerPCCPU *cpu, vaddr eaddr,
 env->error_code = 0;
 }
 env->spr[SPR_DMISS] = eaddr;
-env->spr[SPR_DCMP] = 0x8000 | ctx.ptem;
+env->spr[SPR_DCMP] |= 0x8000;
 tlb_miss:
 env->error_code |= ctx.key << 19;
 env->spr[SPR_HASH1] = ppc_hash32_hpt_base(cpu) +
-- 
2.30.9




[PATCH v7 12/61] target/ppc/mmu_common.c: Split off real mode cases in get_physical_address_wtlb()

2024-05-12 Thread BALATON Zoltan
The real mode handling is identical in the remaining switch cases.
Split off these common real mode cases into a separate conditional to
leave only the else branches in the switch that are different.

Signed-off-by: BALATON Zoltan 
Reviewed-by: Nicholas Piggin 
---
 target/ppc/mmu_common.c | 34 +-
 1 file changed, 9 insertions(+), 25 deletions(-)

diff --git a/target/ppc/mmu_common.c b/target/ppc/mmu_common.c
index 9f177b6976..b13150ce23 100644
--- a/target/ppc/mmu_common.c
+++ b/target/ppc/mmu_common.c
@@ -1172,7 +1172,6 @@ int get_physical_address_wtlb(CPUPPCState *env, mmu_ctx_t 
*ctx,
  MMUAccessType access_type, int type,
  int mmu_idx)
 {
-int ret = -1;
 bool real_mode;
 
 if (env->mmu_model == POWERPC_MMU_BOOKE) {
@@ -1184,38 +1183,23 @@ int get_physical_address_wtlb(CPUPPCState *env, 
mmu_ctx_t *ctx,
 
 real_mode = (type == ACCESS_CODE) ? !FIELD_EX64(env->msr, MSR, IR)
   : !FIELD_EX64(env->msr, MSR, DR);
+if (real_mode && (env->mmu_model == POWERPC_MMU_SOFT_6xx ||
+  env->mmu_model == POWERPC_MMU_SOFT_4xx ||
+  env->mmu_model == POWERPC_MMU_REAL)) {
+return check_physical(env, ctx, eaddr, access_type);
+}
 
 switch (env->mmu_model) {
 case POWERPC_MMU_SOFT_6xx:
-if (real_mode) {
-ret = check_physical(env, ctx, eaddr, access_type);
-} else {
-ret = mmu6xx_get_physical_address(env, ctx, eaddr, access_type,
-  type);
-}
-break;
-
+return mmu6xx_get_physical_address(env, ctx, eaddr, access_type, type);
 case POWERPC_MMU_SOFT_4xx:
-if (real_mode) {
-ret = check_physical(env, ctx, eaddr, access_type);
-} else {
-ret = mmu40x_get_physical_address(env, ctx, eaddr, access_type);
-}
-break;
+return mmu40x_get_physical_address(env, ctx, eaddr, access_type);
 case POWERPC_MMU_REAL:
-if (real_mode) {
-ret = check_physical(env, ctx, eaddr, access_type);
-} else {
-cpu_abort(env_cpu(env),
-  "PowerPC in real mode do not do any translation\n");
-}
-return -1;
+cpu_abort(env_cpu(env),
+  "PowerPC in real mode do not do any translation\n");
 default:
 cpu_abort(env_cpu(env), "Unknown or invalid MMU model\n");
-return -1;
 }
-
-return ret;
 }
 
 static void booke206_update_mas_tlb_miss(CPUPPCState *env, target_ulong 
address,
-- 
2.30.9




[PATCH v7 38/61] target/ppc/mmu_common.c: Remove single use local variable

2024-05-12 Thread BALATON Zoltan
The ptev variable in ppc6xx_tlb_pte_check() is used only once and just
obfuscates an otherwise clear value. Get rid of it.

Signed-off-by: BALATON Zoltan 
---
 target/ppc/mmu_common.c | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/target/ppc/mmu_common.c b/target/ppc/mmu_common.c
index 4ca700e31b..b25c77c618 100644
--- a/target/ppc/mmu_common.c
+++ b/target/ppc/mmu_common.c
@@ -98,13 +98,12 @@ static int ppc6xx_tlb_pte_check(mmu_ctx_t *ctx, 
target_ulong pte0,
 target_ulong pte1, int h,
 MMUAccessType access_type)
 {
-int ret, pteh, ptev, pp;
+int ret, pteh, pp;
 
 ret = -1;
 /* Check validity and table match */
-ptev = pte_is_valid(pte0);
 pteh = (pte0 >> 6) & 1;
-if (ptev && h == pteh) {
+if (pte_is_valid(pte0) && h == pteh) {
 /* Check vsid & api */
 pp = pte1 & 0x0003;
 if ((pte0 & PTE_PTEM_MASK) == ctx->ptem) {
-- 
2.30.9




[PATCH v7 08/61] target/ppc/mmu_common.c: Move else branch to avoid large if block

2024-05-12 Thread BALATON Zoltan
In mmu6xx_get_physical_address() we have a large if block with a two
line else branch that effectively returns. Invert the condition and
move the else there to allow deindenting the large if block to make
the flow easier to follow.

Signed-off-by: BALATON Zoltan 
Reviewed-by: Nicholas Piggin 
---
 target/ppc/mmu_common.c | 71 -
 1 file changed, 34 insertions(+), 37 deletions(-)

diff --git a/target/ppc/mmu_common.c b/target/ppc/mmu_common.c
index b7c07cf515..ba60b4902b 100644
--- a/target/ppc/mmu_common.c
+++ b/target/ppc/mmu_common.c
@@ -405,47 +405,44 @@ static int mmu6xx_get_physical_address(CPUPPCState *env, 
mmu_ctx_t *ctx,
 ret = -1;
 if (!ds) {
 /* Check if instruction fetch is allowed, if needed */
-if (type != ACCESS_CODE || ctx->nx == 0) {
-/* Page address translation */
-qemu_log_mask(CPU_LOG_MMU, "htab_base " HWADDR_FMT_plx
-" htab_mask " HWADDR_FMT_plx
-" hash " HWADDR_FMT_plx "\n",
-ppc_hash32_hpt_base(cpu), ppc_hash32_hpt_mask(cpu), hash);
-ctx->hash[0] = hash;
-ctx->hash[1] = ~hash;
-
-/* Initialize real address with an invalid value */
-ctx->raddr = (hwaddr)-1ULL;
-/* Software TLB search */
-ret = ppc6xx_tlb_check(env, ctx, eaddr, access_type);
+if (type == ACCESS_CODE && ctx->nx) {
+qemu_log_mask(CPU_LOG_MMU, "No access allowed\n");
+return -3;
+}
+/* Page address translation */
+qemu_log_mask(CPU_LOG_MMU, "htab_base " HWADDR_FMT_plx " htab_mask "
+  HWADDR_FMT_plx " hash " HWADDR_FMT_plx "\n",
+  ppc_hash32_hpt_base(cpu), ppc_hash32_hpt_mask(cpu), 
hash);
+ctx->hash[0] = hash;
+ctx->hash[1] = ~hash;
+
+/* Initialize real address with an invalid value */
+ctx->raddr = (hwaddr)-1ULL;
+/* Software TLB search */
+ret = ppc6xx_tlb_check(env, ctx, eaddr, access_type);
 #if defined(DUMP_PAGE_TABLES)
-if (qemu_loglevel_mask(CPU_LOG_MMU)) {
-CPUState *cs = env_cpu(env);
-hwaddr curaddr;
-uint32_t a0, a1, a2, a3;
-
-qemu_log("Page table: " HWADDR_FMT_plx " len " HWADDR_FMT_plx
- "\n", ppc_hash32_hpt_base(cpu),
- ppc_hash32_hpt_mask(cpu) + 0x80);
-for (curaddr = ppc_hash32_hpt_base(cpu);
- curaddr < (ppc_hash32_hpt_base(cpu)
-+ ppc_hash32_hpt_mask(cpu) + 0x80);
- curaddr += 16) {
-a0 = ldl_phys(cs->as, curaddr);
-a1 = ldl_phys(cs->as, curaddr + 4);
-a2 = ldl_phys(cs->as, curaddr + 8);
-a3 = ldl_phys(cs->as, curaddr + 12);
-if (a0 != 0 || a1 != 0 || a2 != 0 || a3 != 0) {
-qemu_log(HWADDR_FMT_plx ": %08x %08x %08x %08x\n",
- curaddr, a0, a1, a2, a3);
-}
+if (qemu_loglevel_mask(CPU_LOG_MMU)) {
+CPUState *cs = env_cpu(env);
+hwaddr curaddr;
+uint32_t a0, a1, a2, a3;
+
+qemu_log("Page table: " HWADDR_FMT_plx " len " HWADDR_FMT_plx "\n",
+ ppc_hash32_hpt_base(cpu), ppc_hash32_hpt_mask(cpu) + 
0x80);
+for (curaddr = ppc_hash32_hpt_base(cpu);
+ curaddr < (ppc_hash32_hpt_base(cpu)
++ ppc_hash32_hpt_mask(cpu) + 0x80);
+ curaddr += 16) {
+a0 = ldl_phys(cs->as, curaddr);
+a1 = ldl_phys(cs->as, curaddr + 4);
+a2 = ldl_phys(cs->as, curaddr + 8);
+a3 = ldl_phys(cs->as, curaddr + 12);
+if (a0 != 0 || a1 != 0 || a2 != 0 || a3 != 0) {
+qemu_log(HWADDR_FMT_plx ": %08x %08x %08x %08x\n",
+ curaddr, a0, a1, a2, a3);
 }
 }
-#endif
-} else {
-qemu_log_mask(CPU_LOG_MMU, "No access allowed\n");
-ret = -3;
 }
+#endif
 } else {
 qemu_log_mask(CPU_LOG_MMU, "direct store...\n");
 /* Direct-store segment : absolutely *BUGGY* for now */
-- 
2.30.9




[PATCH v7 47/61] target/ppc/mmu_common.c: Remove single use local variable

2024-05-12 Thread BALATON Zoltan
In mmu6xx_get_physical_address() tagtet_page_bits local is declared
only to use TARGET_PAGE_BITS once. Drop the unneeded variable.

Signed-off-by: BALATON Zoltan 
---
 target/ppc/mmu_common.c | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/target/ppc/mmu_common.c b/target/ppc/mmu_common.c
index 9b73581fc7..1a2b4158d5 100644
--- a/target/ppc/mmu_common.c
+++ b/target/ppc/mmu_common.c
@@ -321,7 +321,6 @@ static int mmu6xx_get_physical_address(CPUPPCState *env, 
mmu_ctx_t *ctx,
 PowerPCCPU *cpu = env_archcpu(env);
 hwaddr hash;
 target_ulong vsid, sr, pgidx;
-int target_page_bits;
 bool pr, ds, nx;
 
 /* First try to find a BAT entry if there are any */
@@ -338,7 +337,6 @@ static int mmu6xx_get_physical_address(CPUPPCState *env, 
mmu_ctx_t *ctx,
 ds = sr & SR32_T;
 nx = sr & SR32_NX;
 vsid = sr & SR32_VSID;
-target_page_bits = TARGET_PAGE_BITS;
 qemu_log_mask(CPU_LOG_MMU,
   "Check segment v=" TARGET_FMT_lx " %d " TARGET_FMT_lx
   " nip=" TARGET_FMT_lx " lr=" TARGET_FMT_lx
@@ -347,7 +345,7 @@ static int mmu6xx_get_physical_address(CPUPPCState *env, 
mmu_ctx_t *ctx,
   (int)FIELD_EX64(env->msr, MSR, IR),
   (int)FIELD_EX64(env->msr, MSR, DR), pr ? 1 : 0,
   access_type == MMU_DATA_STORE, type);
-pgidx = (eaddr & ~SEGMENT_MASK_256M) >> target_page_bits;
+pgidx = (eaddr & ~SEGMENT_MASK_256M) >> TARGET_PAGE_BITS;
 hash = vsid ^ pgidx;
 ctx->ptem = (vsid << 7) | (pgidx >> 10);
 
-- 
2.30.9




[PATCH v7 39/61] target/ppc/mmu_common.c: Remove another single use local

2024-05-12 Thread BALATON Zoltan
In ppc6xx_tlb_pte_check() the pteh variable is used only once to
compare to the h parameter of the function. Inline its value and use
pteh name for the function parameter which is more descriptive.

Signed-off-by: BALATON Zoltan 
---
 target/ppc/mmu_common.c | 7 +++
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/target/ppc/mmu_common.c b/target/ppc/mmu_common.c
index b25c77c618..7026b6a62c 100644
--- a/target/ppc/mmu_common.c
+++ b/target/ppc/mmu_common.c
@@ -95,15 +95,14 @@ int ppc6xx_tlb_getnum(CPUPPCState *env, target_ulong eaddr,
 }
 
 static int ppc6xx_tlb_pte_check(mmu_ctx_t *ctx, target_ulong pte0,
-target_ulong pte1, int h,
+target_ulong pte1, int pteh,
 MMUAccessType access_type)
 {
-int ret, pteh, pp;
+int ret, pp;
 
 ret = -1;
 /* Check validity and table match */
-pteh = (pte0 >> 6) & 1;
-if (pte_is_valid(pte0) && h == pteh) {
+if (pte_is_valid(pte0) && ((pte0 >> 6) & 1) == pteh) {
 /* Check vsid & api */
 pp = pte1 & 0x0003;
 if ((pte0 & PTE_PTEM_MASK) == ctx->ptem) {
-- 
2.30.9




[PATCH v7 19/61] target/ppc/mmu_common.c: Don't use mmu_ctx_t in mmubooke206_get_physical_address()

2024-05-12 Thread BALATON Zoltan
mmubooke206_get_physical_address() only uses the raddr and prot fields
from mmu_ctx_t. Pass these directly instead of using a ctx struct.

Signed-off-by: BALATON Zoltan 
Reviewed-by: Nicholas Piggin 
---
 target/ppc/mmu_common.c | 32 ++--
 1 file changed, 10 insertions(+), 22 deletions(-)

diff --git a/target/ppc/mmu_common.c b/target/ppc/mmu_common.c
index 12dac9e63a..004ea2111d 100644
--- a/target/ppc/mmu_common.c
+++ b/target/ppc/mmu_common.c
@@ -836,27 +836,22 @@ found_tlb:
 return access_type == MMU_INST_FETCH ? -3 : -2;
 }
 
-static int mmubooke206_get_physical_address(CPUPPCState *env, mmu_ctx_t *ctx,
-target_ulong address,
+static int mmubooke206_get_physical_address(CPUPPCState *env, hwaddr *raddr,
+int *prot, target_ulong address,
 MMUAccessType access_type,
 int mmu_idx)
 {
 ppcmas_tlb_t *tlb;
-hwaddr raddr;
-int i, j, ret;
-
-ret = -1;
-raddr = (hwaddr)-1ULL;
+int i, j, ret = -1;
 
 for (i = 0; i < BOOKE206_MAX_TLBN; i++) {
 int ways = booke206_tlb_ways(env, i);
-
 for (j = 0; j < ways; j++) {
 tlb = booke206_get_tlbm(env, i, address, j);
 if (!tlb) {
 continue;
 }
-ret = mmubooke206_check_tlb(env, tlb, , >prot, address,
+ret = mmubooke206_check_tlb(env, tlb, raddr, prot, address,
 access_type, mmu_idx);
 if (ret != -1) {
 goto found_tlb;
@@ -866,17 +861,10 @@ static int mmubooke206_get_physical_address(CPUPPCState 
*env, mmu_ctx_t *ctx,
 
 found_tlb:
 
-if (ret >= 0) {
-ctx->raddr = raddr;
- qemu_log_mask(CPU_LOG_MMU, "%s: access granted " TARGET_FMT_lx
-   " => " HWADDR_FMT_plx " %d %d\n", __func__, address,
-   ctx->raddr, ctx->prot, ret);
-} else {
- qemu_log_mask(CPU_LOG_MMU, "%s: access refused " TARGET_FMT_lx
-   " => " HWADDR_FMT_plx " %d %d\n", __func__, address,
-   raddr, ctx->prot, ret);
-}
-
+qemu_log_mask(CPU_LOG_MMU, "%s: access %s " TARGET_FMT_lx " => "
+  HWADDR_FMT_plx " %d %d\n", __func__,
+  ret < 0 ? "refused" : "granted", address,
+  ret < 0 ? -1 : *raddr, ret == -1 ? 0 : *prot, ret);
 return ret;
 }
 
@@ -1135,8 +1123,8 @@ int get_physical_address_wtlb(CPUPPCState *env, mmu_ctx_t 
*ctx,
 return mmubooke_get_physical_address(env, >raddr, >prot,
  eaddr, access_type);
 } else if (env->mmu_model == POWERPC_MMU_BOOKE206) {
-return mmubooke206_get_physical_address(env, ctx, eaddr, access_type,
-mmu_idx);
+return mmubooke206_get_physical_address(env, >raddr, >prot,
+eaddr, access_type, mmu_idx);
 }
 
 real_mode = (type == ACCESS_CODE) ? !FIELD_EX64(env->msr, MSR, IR)
-- 
2.30.9




[PATCH v7 45/61] target/ppc/mmu_common.c: Remove nx field from mmu_ctx_t

2024-05-12 Thread BALATON Zoltan
Pass it as a parameter instead. Also use named constants instead of
hex values when extracting bits from SR.

Signed-off-by: BALATON Zoltan 
---
 target/ppc/mmu_common.c | 24 
 1 file changed, 12 insertions(+), 12 deletions(-)

diff --git a/target/ppc/mmu_common.c b/target/ppc/mmu_common.c
index ccacc70ba6..b1ae32f39f 100644
--- a/target/ppc/mmu_common.c
+++ b/target/ppc/mmu_common.c
@@ -43,7 +43,6 @@ typedef struct {
 int prot;  /* Protection bits  */
 target_ulong ptem; /* Virtual segment ID | API */
 int key;   /* Access key   */
-int nx;/* Non-execute area */
 } mmu_ctx_t;
 
 void ppc_store_sdr1(CPUPPCState *env, target_ulong value)
@@ -94,7 +93,7 @@ int ppc6xx_tlb_getnum(CPUPPCState *env, target_ulong eaddr,
 
 static int ppc6xx_tlb_pte_check(mmu_ctx_t *ctx, target_ulong pte0,
 target_ulong pte1, int pteh,
-MMUAccessType access_type)
+MMUAccessType access_type, bool nx)
 {
 /* Check validity and table match */
 if (!pte_is_valid(pte0) || ((pte0 >> 6) & 1) != pteh ||
@@ -109,7 +108,7 @@ static int ppc6xx_tlb_pte_check(mmu_ctx_t *ctx, 
target_ulong pte0,
 }
 /* Keep the matching PTE information */
 ctx->raddr = pte1;
-ctx->prot = ppc_hash32_pp_prot(ctx->key, pte1 & HPTE32_R_PP, ctx->nx);
+ctx->prot = ppc_hash32_pp_prot(ctx->key, pte1 & HPTE32_R_PP, nx);
 if (check_prot_access_type(ctx->prot, access_type)) {
 qemu_log_mask(CPU_LOG_MMU, "PTE access granted !\n");
 return 0;
@@ -121,8 +120,9 @@ static int ppc6xx_tlb_pte_check(mmu_ctx_t *ctx, 
target_ulong pte0,
 
 /* Software driven TLB helpers */
 
-static int ppc6xx_tlb_check(CPUPPCState *env, mmu_ctx_t *ctx,
-target_ulong eaddr, MMUAccessType access_type)
+static int ppc6xx_tlb_check(CPUPPCState *env,
+mmu_ctx_t *ctx, target_ulong eaddr,
+MMUAccessType access_type, bool nx)
 {
 ppc6xx_tlb_t *tlb;
 target_ulong *pte1p;
@@ -150,7 +150,7 @@ static int ppc6xx_tlb_check(CPUPPCState *env, mmu_ctx_t 
*ctx,
   access_type == MMU_DATA_STORE ? 'S' : 'L',
   access_type == MMU_INST_FETCH ? 'I' : 'D');
 switch (ppc6xx_tlb_pte_check(ctx, tlb->pte0, tlb->pte1,
- 0, access_type)) {
+ 0, access_type, nx)) {
 case -2:
 /* Access violation */
 ret = -2;
@@ -322,7 +322,7 @@ static int mmu6xx_get_physical_address(CPUPPCState *env, 
mmu_ctx_t *ctx,
 hwaddr hash;
 target_ulong vsid, sr, pgidx;
 int ds, target_page_bits;
-bool pr;
+bool pr, nx;
 
 /* First try to find a BAT entry if there are any */
 if (env->nb_BATs && get_bat_6xx_tlb(env, ctx, eaddr, access_type) == 0) {
@@ -336,8 +336,8 @@ static int mmu6xx_get_physical_address(CPUPPCState *env, 
mmu_ctx_t *ctx,
 ctx->key = (((sr & 0x2000) && pr) ||
 ((sr & 0x4000) && !pr)) ? 1 : 0;
 ds = sr & 0x8000 ? 1 : 0;
-ctx->nx = sr & 0x1000 ? 1 : 0;
-vsid = sr & 0x00FF;
+nx = sr & SR32_NX;
+vsid = sr & SR32_VSID;
 target_page_bits = TARGET_PAGE_BITS;
 qemu_log_mask(CPU_LOG_MMU,
   "Check segment v=" TARGET_FMT_lx " %d " TARGET_FMT_lx
@@ -352,10 +352,10 @@ static int mmu6xx_get_physical_address(CPUPPCState *env, 
mmu_ctx_t *ctx,
 ctx->ptem = (vsid << 7) | (pgidx >> 10);
 
 qemu_log_mask(CPU_LOG_MMU, "pte segment: key=%d ds %d nx %d vsid "
-  TARGET_FMT_lx "\n", ctx->key, ds, ctx->nx, vsid);
+  TARGET_FMT_lx "\n", ctx->key, ds, nx, vsid);
 if (!ds) {
 /* Check if instruction fetch is allowed, if needed */
-if (type == ACCESS_CODE && ctx->nx) {
+if (type == ACCESS_CODE && nx) {
 qemu_log_mask(CPU_LOG_MMU, "No access allowed\n");
 return -3;
 }
@@ -368,7 +368,7 @@ static int mmu6xx_get_physical_address(CPUPPCState *env, 
mmu_ctx_t *ctx,
 /* Initialize real address with an invalid value */
 ctx->raddr = (hwaddr)-1ULL;
 /* Software TLB search */
-return ppc6xx_tlb_check(env, ctx, eaddr, access_type);
+return ppc6xx_tlb_check(env, ctx, eaddr, access_type, nx);
 }
 
 /* Direct-store segment : absolutely *BUGGY* for now */
-- 
2.30.9




[PATCH v7 34/61] target/ppc: Move out BookE and related MMU functions from mmu_common.c

2024-05-12 Thread BALATON Zoltan
Add a new mmu-booke.c file for BookE and related MMU bits from
mmu_common.c.

Signed-off-by: BALATON Zoltan 
Acked-by: Nicholas Piggin 
---
 target/ppc/cpu.h|   4 -
 target/ppc/meson.build  |   1 +
 target/ppc/mmu-booke.c  | 531 
 target/ppc/mmu-booke.h  |  17 ++
 target/ppc/mmu_common.c | 507 +-
 target/ppc/mmu_helper.c |   1 +
 6 files changed, 551 insertions(+), 510 deletions(-)
 create mode 100644 target/ppc/mmu-booke.c
 create mode 100644 target/ppc/mmu-booke.h

diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h
index cfb3ba5ac8..92b50a1be2 100644
--- a/target/ppc/cpu.h
+++ b/target/ppc/cpu.h
@@ -1606,10 +1606,6 @@ void ppc_tlb_invalidate_all(CPUPPCState *env);
 void ppc_tlb_invalidate_one(CPUPPCState *env, target_ulong addr);
 void cpu_ppc_set_vhyp(PowerPCCPU *cpu, PPCVirtualHypervisor *vhyp);
 void cpu_ppc_set_1lpar(PowerPCCPU *cpu);
-int ppcmas_tlb_check(CPUPPCState *env, ppcmas_tlb_t *tlb, hwaddr *raddrp,
- target_ulong address, uint32_t pid);
-int ppcemb_tlb_search(CPUPPCState *env, target_ulong address, uint32_t pid);
-hwaddr booke206_tlb_to_page_size(CPUPPCState *env, ppcmas_tlb_t *tlb);
 #endif
 
 void ppc_store_fpscr(CPUPPCState *env, target_ulong val);
diff --git a/target/ppc/meson.build b/target/ppc/meson.build
index 0b89f9b89f..db3b7a0c33 100644
--- a/target/ppc/meson.build
+++ b/target/ppc/meson.build
@@ -37,6 +37,7 @@ ppc_system_ss.add(files(
   'arch_dump.c',
   'machine.c',
   'mmu-hash32.c',
+  'mmu-booke.c',
   'mmu_common.c',
   'ppc-qmp-cmds.c',
 ))
diff --git a/target/ppc/mmu-booke.c b/target/ppc/mmu-booke.c
new file mode 100644
index 00..55e5dd7c6b
--- /dev/null
+++ b/target/ppc/mmu-booke.c
@@ -0,0 +1,531 @@
+/*
+ *  PowerPC BookE MMU, TLB emulation helpers for QEMU.
+ *
+ *  Copyright (c) 2003-2007 Jocelyn Mayer
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see .
+ */
+
+#include "qemu/osdep.h"
+#include "exec/page-protection.h"
+#include "exec/log.h"
+#include "cpu.h"
+#include "internal.h"
+#include "mmu-booke.h"
+
+/* Generic TLB check function for embedded PowerPC implementations */
+static bool ppcemb_tlb_check(CPUPPCState *env, ppcemb_tlb_t *tlb,
+ hwaddr *raddrp,
+ target_ulong address, uint32_t pid, int i)
+{
+target_ulong mask;
+
+/* Check valid flag */
+if (!(tlb->prot & PAGE_VALID)) {
+return false;
+}
+mask = ~(tlb->size - 1);
+qemu_log_mask(CPU_LOG_MMU, "%s: TLB %d address " TARGET_FMT_lx
+  " PID %u <=> " TARGET_FMT_lx " " TARGET_FMT_lx " %u %x\n",
+  __func__, i, address, pid, tlb->EPN,
+  mask, (uint32_t)tlb->PID, tlb->prot);
+/* Check PID */
+if (tlb->PID != 0 && tlb->PID != pid) {
+return false;
+}
+/* Check effective address */
+if ((address & mask) != tlb->EPN) {
+return false;
+}
+*raddrp = (tlb->RPN & mask) | (address & ~mask);
+return true;
+}
+
+/* Generic TLB search function for PowerPC embedded implementations */
+int ppcemb_tlb_search(CPUPPCState *env, target_ulong address, uint32_t pid)
+{
+ppcemb_tlb_t *tlb;
+hwaddr raddr;
+int i;
+
+for (i = 0; i < env->nb_tlb; i++) {
+tlb = >tlb.tlbe[i];
+if (ppcemb_tlb_check(env, tlb, , address, pid, i)) {
+return i;
+}
+}
+return -1;
+}
+
+int mmu40x_get_physical_address(CPUPPCState *env, hwaddr *raddr, int *prot,
+target_ulong address,
+MMUAccessType access_type)
+{
+ppcemb_tlb_t *tlb;
+int i, ret, zsel, zpr, pr;
+
+ret = -1;
+pr = FIELD_EX64(env->msr, MSR, PR);
+for (i = 0; i < env->nb_tlb; i++) {
+tlb = >tlb.tlbe[i];
+if (!ppcemb_tlb_check(env, tlb, raddr, address,
+  env->spr[SPR_40x_PID], i)) {
+continue;
+}
+zsel = (tlb->attr >> 4) & 0xF;
+zpr = (env->spr[SPR_40x_ZPR] >> (30 - (2 * zsel))) & 0x3;
+qemu_log_mask(CPU_LOG_MMU,
+  "%s: TLB %d zsel %d zpr %d ty %d attr %08x\n",
+  __func__, i, zsel, zpr, access_type, tlb->attr);
+/* Check execute enable bit */
+switch (zpr) {
+case 0x2:
+if (pr != 0) 

[PATCH v7 29/61] target/ppc: Remove id_tlbs flag from CPU env

2024-05-12 Thread BALATON Zoltan
This flag for split instruction/data TLBs is only set for 6xx soft TLB
MMU model and not used otherwise so no need to have a separate flag
for that.

Signed-off-by: BALATON Zoltan 
Reviewed-by: Nicholas Piggin 
---
 hw/ppc/pegasos2.c|  2 +-
 target/ppc/cpu.h |  5 -
 target/ppc/cpu_init.c| 19 +--
 target/ppc/helper_regs.c |  1 -
 target/ppc/mmu_common.c  | 10 ++
 target/ppc/mmu_helper.c  | 12 ++--
 6 files changed, 14 insertions(+), 35 deletions(-)

diff --git a/hw/ppc/pegasos2.c b/hw/ppc/pegasos2.c
index 04d6decb2b..750f439c5d 100644
--- a/hw/ppc/pegasos2.c
+++ b/hw/ppc/pegasos2.c
@@ -984,7 +984,7 @@ static void *build_fdt(MachineState *machine, int *fdt_size)
   cpu->env.icache_line_size);
 qemu_fdt_setprop_cell(fdt, cp, "i-cache-line-size",
   cpu->env.icache_line_size);
-if (cpu->env.id_tlbs) {
+if (ppc_is_split_tlb(cpu)) {
 qemu_fdt_setprop_cell(fdt, cp, "i-tlb-sets", cpu->env.nb_ways);
 qemu_fdt_setprop_cell(fdt, cp, "i-tlb-size", cpu->env.tlb_per_way);
 qemu_fdt_setprop_cell(fdt, cp, "d-tlb-sets", cpu->env.nb_ways);
diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h
index 0ac55d6b25..cfb3ba5ac8 100644
--- a/target/ppc/cpu.h
+++ b/target/ppc/cpu.h
@@ -1260,7 +1260,6 @@ struct CPUArchState {
 int tlb_per_way; /* Speed-up helper: used to avoid divisions at run time */
 int nb_ways; /* Number of ways in the TLB set */
 int last_way;/* Last used way used to allocate TLB in a LRU way */
-int id_tlbs; /* If 1, MMU has separated TLBs for instructions & data */
 int nb_pids; /* Number of available PID registers */
 int tlb_type;/* Type of TLB we're dealing with */
 ppc_tlb_t tlb;   /* TLB is optional. Allocate them only if needed */
@@ -2856,6 +2855,10 @@ static inline void booke206_fixed_size_tlbn(CPUPPCState 
*env, const int tlbn,
 tlb->mas1 |= ((uint32_t)tsize) << MAS1_TSIZE_SHIFT;
 }
 
+static inline bool ppc_is_split_tlb(PowerPCCPU *cpu)
+{
+return cpu->env.tlb_type == TLB_6XX;
+}
 #endif
 
 static inline bool msr_is_64bit(CPUPPCState *env, target_ulong msr)
diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c
index c11a69fd90..07ad788e54 100644
--- a/target/ppc/cpu_init.c
+++ b/target/ppc/cpu_init.c
@@ -2117,7 +2117,6 @@ static void init_proc_405(CPUPPCState *env)
 #if !defined(CONFIG_USER_ONLY)
 env->nb_tlb = 64;
 env->nb_ways = 1;
-env->id_tlbs = 0;
 env->tlb_type = TLB_EMB;
 #endif
 init_excp_4xx(env);
@@ -2190,7 +2189,6 @@ static void init_proc_440EP(CPUPPCState *env)
 #if !defined(CONFIG_USER_ONLY)
 env->nb_tlb = 64;
 env->nb_ways = 1;
-env->id_tlbs = 0;
 env->tlb_type = TLB_EMB;
 #endif
 init_excp_BookE(env);
@@ -2288,7 +2286,6 @@ static void init_proc_440GP(CPUPPCState *env)
 #if !defined(CONFIG_USER_ONLY)
 env->nb_tlb = 64;
 env->nb_ways = 1;
-env->id_tlbs = 0;
 env->tlb_type = TLB_EMB;
 #endif
 init_excp_BookE(env);
@@ -2362,7 +2359,6 @@ static void init_proc_440x5(CPUPPCState *env)
 #if !defined(CONFIG_USER_ONLY)
 env->nb_tlb = 64;
 env->nb_ways = 1;
-env->id_tlbs = 0;
 env->tlb_type = TLB_EMB;
 #endif
 init_excp_BookE(env);
@@ -2724,7 +2720,6 @@ static void init_proc_e200(CPUPPCState *env)
 #if !defined(CONFIG_USER_ONLY)
 env->nb_tlb = 64;
 env->nb_ways = 1;
-env->id_tlbs = 0;
 env->tlb_type = TLB_EMB;
 #endif
 init_excp_e200(env, 0xUL);
@@ -2843,7 +2838,6 @@ static void init_proc_e500(CPUPPCState *env, int version)
 /* Memory management */
 env->nb_pids = 3;
 env->nb_ways = 2;
-env->id_tlbs = 0;
 switch (version) {
 case fsl_e500v1:
 tlbncfg[0] = register_tlbncfg(2, 1, 1, 0, 256);
@@ -6800,20 +6794,17 @@ static void init_ppc_proc(PowerPCCPU *cpu)
 }
 /* Allocate TLBs buffer when needed */
 #if !defined(CONFIG_USER_ONLY)
-if (env->nb_tlb != 0) {
-int nb_tlb = env->nb_tlb;
-if (env->id_tlbs != 0) {
-nb_tlb *= 2;
-}
+if (env->nb_tlb) {
 switch (env->tlb_type) {
 case TLB_6XX:
-env->tlb.tlb6 = g_new0(ppc6xx_tlb_t, nb_tlb);
+/* 6xx has separate TLBs for instructions and data hence times 2 */
+env->tlb.tlb6 = g_new0(ppc6xx_tlb_t, 2 * env->nb_tlb);
 break;
 case TLB_EMB:
-env->tlb.tlbe = g_new0(ppcemb_tlb_t, nb_tlb);
+env->tlb.tlbe = g_new0(ppcemb_tlb_t, env->nb_tlb);
 break;
 case TLB_MAS:
-env->tlb.tlbm = g_new0(ppcmas_tlb_t, nb_tlb);
+env->tlb.tlbm = g_new0(ppcmas_tlb_t, env->nb_tlb);
 break;
 }
 /* Pre-compute some useful values */
diff --git a/target/ppc/helper_regs.c b/target/ppc/helper_regs.c
index 25258986e3..ed583fe9b3 100644
--- a/target/ppc/helper_regs.c
+++ b/target/ppc/helper_regs.c
@@ -693,7 +693,6 @@ void 

[PATCH v7 43/61] target/ppc/mmu_common.c: Remove unused field from mmu_ctx_t

2024-05-12 Thread BALATON Zoltan
The eaddr field of mmu_ctx_t is set once but never used so can be
removed.

Signed-off-by: BALATON Zoltan 
---
 target/ppc/mmu_common.c | 2 --
 1 file changed, 2 deletions(-)

diff --git a/target/ppc/mmu_common.c b/target/ppc/mmu_common.c
index 564fcc7cfb..07c127d673 100644
--- a/target/ppc/mmu_common.c
+++ b/target/ppc/mmu_common.c
@@ -40,7 +40,6 @@
 /* Context used internally during MMU translations */
 typedef struct {
 hwaddr raddr;  /* Real address */
-hwaddr eaddr;  /* Effective address*/
 int prot;  /* Protection bits  */
 hwaddr hash[2];/* Pagetable hash values*/
 target_ulong ptem; /* Virtual segment ID | API */
@@ -333,7 +332,6 @@ static int mmu6xx_get_physical_address(CPUPPCState *env, 
mmu_ctx_t *ctx,
 
 /* Perform segment based translation when no BATs matched */
 pr = FIELD_EX64(env->msr, MSR, PR);
-ctx->eaddr = eaddr;
 
 sr = env->sr[eaddr >> 28];
 ctx->key = (((sr & 0x2000) && pr) ||
-- 
2.30.9




[PATCH v7 13/61] target/ppc/mmu_common.c: Inline and remove check_physical()

2024-05-12 Thread BALATON Zoltan
This function just does two assignments and and unnecessary check that
is always true so inline it in the only caller left and remove it.

Signed-off-by: BALATON Zoltan 
Reviewed-by: Nicholas Piggin 
---
 target/ppc/mmu_common.c | 26 +++---
 1 file changed, 3 insertions(+), 23 deletions(-)

diff --git a/target/ppc/mmu_common.c b/target/ppc/mmu_common.c
index b13150ce23..2f412dd7c5 100644
--- a/target/ppc/mmu_common.c
+++ b/target/ppc/mmu_common.c
@@ -1145,28 +1145,6 @@ void dump_mmu(CPUPPCState *env)
 }
 }
 
-static int check_physical(CPUPPCState *env, mmu_ctx_t *ctx, target_ulong eaddr,
-  MMUAccessType access_type)
-{
-ctx->raddr = eaddr;
-ctx->prot = PAGE_READ | PAGE_EXEC;
-
-switch (env->mmu_model) {
-case POWERPC_MMU_SOFT_6xx:
-case POWERPC_MMU_SOFT_4xx:
-case POWERPC_MMU_REAL:
-case POWERPC_MMU_BOOKE:
-ctx->prot |= PAGE_WRITE;
-break;
-
-default:
-/* Caller's checks mean we should never get here for other models */
-g_assert_not_reached();
-}
-
-return 0;
-}
-
 int get_physical_address_wtlb(CPUPPCState *env, mmu_ctx_t *ctx,
  target_ulong eaddr,
  MMUAccessType access_type, int type,
@@ -1186,7 +1164,9 @@ int get_physical_address_wtlb(CPUPPCState *env, mmu_ctx_t 
*ctx,
 if (real_mode && (env->mmu_model == POWERPC_MMU_SOFT_6xx ||
   env->mmu_model == POWERPC_MMU_SOFT_4xx ||
   env->mmu_model == POWERPC_MMU_REAL)) {
-return check_physical(env, ctx, eaddr, access_type);
+ctx->raddr = eaddr;
+ctx->prot = PAGE_RWX;
+return 0;
 }
 
 switch (env->mmu_model) {
-- 
2.30.9




[PATCH v7 46/61] target/ppc/mmu_common.c: Convert local variable to bool

2024-05-12 Thread BALATON Zoltan
In mmu6xx_get_physical_address() ds is used as bool, declare it as
such. Also use named constant instead of hex value.

Signed-off-by: BALATON Zoltan 
---
 target/ppc/mmu_common.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/target/ppc/mmu_common.c b/target/ppc/mmu_common.c
index b1ae32f39f..9b73581fc7 100644
--- a/target/ppc/mmu_common.c
+++ b/target/ppc/mmu_common.c
@@ -321,8 +321,8 @@ static int mmu6xx_get_physical_address(CPUPPCState *env, 
mmu_ctx_t *ctx,
 PowerPCCPU *cpu = env_archcpu(env);
 hwaddr hash;
 target_ulong vsid, sr, pgidx;
-int ds, target_page_bits;
-bool pr, nx;
+int target_page_bits;
+bool pr, ds, nx;
 
 /* First try to find a BAT entry if there are any */
 if (env->nb_BATs && get_bat_6xx_tlb(env, ctx, eaddr, access_type) == 0) {
@@ -335,7 +335,7 @@ static int mmu6xx_get_physical_address(CPUPPCState *env, 
mmu_ctx_t *ctx,
 sr = env->sr[eaddr >> 28];
 ctx->key = (((sr & 0x2000) && pr) ||
 ((sr & 0x4000) && !pr)) ? 1 : 0;
-ds = sr & 0x8000 ? 1 : 0;
+ds = sr & SR32_T;
 nx = sr & SR32_NX;
 vsid = sr & SR32_VSID;
 target_page_bits = TARGET_PAGE_BITS;
-- 
2.30.9




[PATCH v7 00/61] Misc PPC exception and BookE MMU clean ups

2024-05-12 Thread BALATON Zoltan
This series does some further clean up mostly around BookE MMU to
untangle it from other MMU models. It also contains some other changes
that I've come up with while working on this. The Simplify
ppc_booke_xlate() part 1 and part 2 patches could be squashed together
but left them separate for easier review. This could still be continued
which I might do in the future but this is long enough now to be merged.

v7:
- Added more clean ups

v6:
- Finish breaking up ppc_jumbo_xlate by MMU model as the TODO comment
said and remove it completely
- Add some more small clean ups

v5:
- drop sc patches from this series
- eliminate uninit warning work arounds and also get rid of
get_physical_address_wtlb() (one memset is still needed temporarily
but can be removed at the end)
- use function instead of macro

v4:
- Add a (probably redundant) check for MPC8xx case in ppc_xlate so we
don't have to care about it in lower levels
- Detangle BookE related functions from mmu_ctx_t to avoid some used
uninit work arounds and allow these to be moved out to mmu-booke.c
- Some other tweaks asked during review

v3:
- Address review comments from Nick
- Rebase on master
- Squashed some patches together
- Add some more patches I've done since last version

v2:
- Fix user mode issue in patch 1 by keeping old behaviour for user mode
- Add some more MMU clean up patches

Regards,
BALATON Zoltan


Dr. David Alan Gilbert (1):
  target/ppc: Remove unused struct 'mmu_ctx_hash32'

BALATON Zoltan (60):
  target/ppc: Remove unused helper
  target/ppc/mmu_common.c: Move calculation of a value closer to its
usage
  target/ppc/mmu_common.c: Remove unneeded local variable
  target/ppc/mmu_common.c: Simplify checking for real mode
  target/ppc/mmu_common.c: Drop cases for unimplemented MPC8xx MMU
  target/ppc/mmu_common.c: Introduce mmu6xx_get_physical_address()
  target/ppc/mmu_common.c: Move else branch to avoid large if block
  target/ppc/mmu_common.c: Move some debug logging
  target/ppc/mmu_common.c: Eliminate ret from
mmu6xx_get_physical_address()
  target/ppc/mmu_common.c: Split out BookE cases before checking real
mode
  target/ppc/mmu_common.c: Split off real mode cases in
get_physical_address_wtlb()
  target/ppc/mmu_common.c: Inline and remove check_physical()
  target/ppc/mmu_common.c: Fix misindented qemu_log_mask() calls
  target/ppc/mmu_common.c: Deindent ppc_jumbo_xlate()
  target/ppc/mmu_common.c: Replace hard coded constants in
ppc_jumbo_xlate()
  target/ppc/mmu_common.c: Don't use mmu_ctx_t for
mmu40x_get_physical_address()
  target/ppc/mmu_common.c: Don't use mmu_ctx_t in
mmubooke_get_physical_address()
  target/ppc/mmu_common.c: Don't use mmu_ctx_t in
mmubooke206_get_physical_address()
  target/ppc/mmu_common.c: Remove BookE from direct store handling
  target/ppc/mmu_common.c: Split off BookE handling from
ppc_jumbo_xlate()
  target/ppc/mmu_common.c: Simplify ppc_booke_xlate() part 1
  target/ppc/mmu_common.c: Simplify ppc_booke_xlate() part 2
  target/ppc/mmu_common.c: Split off real mode handling from
get_physical_address_wtlb()
  target/ppc/mmu_common.c: Split off 40x cases from ppc_jumbo_xlate()
  target/ppc/mmu_common.c: Transform ppc_jumbo_xlate() into
ppc_6xx_xlate()
  target/ppc/mmu_common.c: Move mmu_ctx_t type to mmu_common.c
  target/ppc/mmu_common.c: Remove pte_update_flags()
  target/ppc: Remove id_tlbs flag from CPU env
  target/ppc: Split off common embedded TLB init
  target/ppc/mmu-hash32.c: Drop a local variable
  target/ppc/mmu-radix64.c: Drop a local variable
  target/ppc: Add a function to check for page protection bit
  target/ppc: Move out BookE and related MMU functions from mmu_common.c
  target/ppc: Remove pp_check() and reuse ppc_hash32_pp_prot()
  target/ppc/mmu_common.c: Remove local name for a constant
  target/ppc/mmu_common.c: Remove single use local variable
  target/ppc/mmu_common.c: Remove single use local variable
  target/ppc/mmu_common.c: Remove another single use local
  target/ppc/mmu_common.c: Remove yet another single use local
  target/ppc/mmu_common.c: Return directly in ppc6xx_tlb_pte_check()
  target/ppc/mmu_common.c: Simplify ppc6xx_tlb_pte_check()
  target/ppc/mmu_common.c: Remove unused field from mmu_ctx_t
  target/ppc/mmu_common.c: Remove hash field from mmu_ctx_t
  target/ppc/mmu_common.c: Remove nx field from mmu_ctx_t
  target/ppc/mmu_common.c: Convert local variable to bool
  target/ppc/mmu_common.c: Remove single use local variable
  target/ppc/mmu_common.c: Simplify a switch statement
  target/ppc/mmu_common.c: Inline and remove ppc6xx_tlb_pte_check()
  target/ppc/mmu_common.c: Remove ptem field from mmu_ctx_t
  target/ppc: Add function to get protection key for hash32 MMU
  target/ppc/mmu-hash32.c: Inline and remove ppc_hash32_pte_prot()
  target/ppc/mmu_common.c: Init variable in function that relies on it
  target/ppc/mmu_common.c: Remove key field from mmu_ctx_t
  target/ppc/mmu_common.c: Stop using ctx in 

[PATCH v7 11/61] target/ppc/mmu_common.c: Split out BookE cases before checking real mode

2024-05-12 Thread BALATON Zoltan
BookE does not have real mode so split off and handle it first in
get_physical_address_wtlb() before checking for real mode for other
MMU models.

Signed-off-by: BALATON Zoltan 
Reviewed-by: Nicholas Piggin 
---
 target/ppc/mmu_common.c | 14 +++---
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/target/ppc/mmu_common.c b/target/ppc/mmu_common.c
index 03d9e6bfda..9f177b6976 100644
--- a/target/ppc/mmu_common.c
+++ b/target/ppc/mmu_common.c
@@ -1175,6 +1175,13 @@ int get_physical_address_wtlb(CPUPPCState *env, 
mmu_ctx_t *ctx,
 int ret = -1;
 bool real_mode;
 
+if (env->mmu_model == POWERPC_MMU_BOOKE) {
+return mmubooke_get_physical_address(env, ctx, eaddr, access_type);
+} else if (env->mmu_model == POWERPC_MMU_BOOKE206) {
+return mmubooke206_get_physical_address(env, ctx, eaddr, access_type,
+mmu_idx);
+}
+
 real_mode = (type == ACCESS_CODE) ? !FIELD_EX64(env->msr, MSR, IR)
   : !FIELD_EX64(env->msr, MSR, DR);
 
@@ -1195,13 +1202,6 @@ int get_physical_address_wtlb(CPUPPCState *env, 
mmu_ctx_t *ctx,
 ret = mmu40x_get_physical_address(env, ctx, eaddr, access_type);
 }
 break;
-case POWERPC_MMU_BOOKE:
-ret = mmubooke_get_physical_address(env, ctx, eaddr, access_type);
-break;
-case POWERPC_MMU_BOOKE206:
-ret = mmubooke206_get_physical_address(env, ctx, eaddr, access_type,
-   mmu_idx);
-break;
 case POWERPC_MMU_REAL:
 if (real_mode) {
 ret = check_physical(env, ctx, eaddr, access_type);
-- 
2.30.9




[PATCH v7 41/61] target/ppc/mmu_common.c: Return directly in ppc6xx_tlb_pte_check()

2024-05-12 Thread BALATON Zoltan
Instead of using a local ret variable return directly and remove the
local.

Signed-off-by: BALATON Zoltan 
---
 target/ppc/mmu_common.c | 10 +++---
 1 file changed, 3 insertions(+), 7 deletions(-)

diff --git a/target/ppc/mmu_common.c b/target/ppc/mmu_common.c
index 0c7cbab2bc..a035cefcad 100644
--- a/target/ppc/mmu_common.c
+++ b/target/ppc/mmu_common.c
@@ -98,9 +98,6 @@ static int ppc6xx_tlb_pte_check(mmu_ctx_t *ctx, target_ulong 
pte0,
 target_ulong pte1, int pteh,
 MMUAccessType access_type)
 {
-int ret;
-
-ret = -1;
 /* Check validity and table match */
 if (pte_is_valid(pte0) && ((pte0 >> 6) & 1) == pteh) {
 /* Check vsid & api */
@@ -119,16 +116,15 @@ static int ppc6xx_tlb_pte_check(mmu_ctx_t *ctx, 
target_ulong pte0,
 if (check_prot_access_type(ctx->prot, access_type)) {
 /* Access granted */
 qemu_log_mask(CPU_LOG_MMU, "PTE access granted !\n");
-ret = 0;
+return 0;
 } else {
 /* Access right violation */
 qemu_log_mask(CPU_LOG_MMU, "PTE access rejected\n");
-ret = -2;
+return -2;
 }
 }
 }
-
-return ret;
+return -1;
 }
 
 /* Software driven TLB helpers */
-- 
2.30.9




[PATCH v7 15/61] target/ppc/mmu_common.c: Deindent ppc_jumbo_xlate()

2024-05-12 Thread BALATON Zoltan
Instead of putting a large block of code in an if, invert the
condition and return early to be able to deindent the code block.

Signed-off-by: BALATON Zoltan 
Acked-by: Nicholas Piggin 
---
 target/ppc/mmu_common.c | 319 
 1 file changed, 159 insertions(+), 160 deletions(-)

diff --git a/target/ppc/mmu_common.c b/target/ppc/mmu_common.c
index 124148b3da..f40481b4b1 100644
--- a/target/ppc/mmu_common.c
+++ b/target/ppc/mmu_common.c
@@ -1264,187 +1264,186 @@ static bool ppc_jumbo_xlate(PowerPCCPU *cpu, vaddr 
eaddr,
 *protp = ctx.prot;
 *psizep = TARGET_PAGE_BITS;
 return true;
+} else if (!guest_visible) {
+return false;
 }
 
-if (guest_visible) {
-log_cpu_state_mask(CPU_LOG_MMU, cs, 0);
-if (type == ACCESS_CODE) {
-switch (ret) {
-case -1:
-/* No matches in page tables or TLB */
-switch (env->mmu_model) {
-case POWERPC_MMU_SOFT_6xx:
-cs->exception_index = POWERPC_EXCP_IFTLB;
-env->error_code = 1 << 18;
-env->spr[SPR_IMISS] = eaddr;
-env->spr[SPR_ICMP] = 0x8000 | ctx.ptem;
-goto tlb_miss;
-case POWERPC_MMU_SOFT_4xx:
-cs->exception_index = POWERPC_EXCP_ITLB;
-env->error_code = 0;
-env->spr[SPR_40x_DEAR] = eaddr;
-env->spr[SPR_40x_ESR] = 0x;
-break;
-case POWERPC_MMU_BOOKE206:
-booke206_update_mas_tlb_miss(env, eaddr, 2, mmu_idx);
-/* fall through */
-case POWERPC_MMU_BOOKE:
-cs->exception_index = POWERPC_EXCP_ITLB;
-env->error_code = 0;
-env->spr[SPR_BOOKE_DEAR] = eaddr;
-env->spr[SPR_BOOKE_ESR] = mmubooke206_esr(mmu_idx, 
MMU_DATA_LOAD);
-break;
-case POWERPC_MMU_REAL:
-cpu_abort(cs, "PowerPC in real mode should never raise "
-  "any MMU exceptions\n");
-default:
-cpu_abort(cs, "Unknown or invalid MMU model\n");
-}
+log_cpu_state_mask(CPU_LOG_MMU, cs, 0);
+if (type == ACCESS_CODE) {
+switch (ret) {
+case -1:
+/* No matches in page tables or TLB */
+switch (env->mmu_model) {
+case POWERPC_MMU_SOFT_6xx:
+cs->exception_index = POWERPC_EXCP_IFTLB;
+env->error_code = 1 << 18;
+env->spr[SPR_IMISS] = eaddr;
+env->spr[SPR_ICMP] = 0x8000 | ctx.ptem;
+goto tlb_miss;
+case POWERPC_MMU_SOFT_4xx:
+cs->exception_index = POWERPC_EXCP_ITLB;
+env->error_code = 0;
+env->spr[SPR_40x_DEAR] = eaddr;
+env->spr[SPR_40x_ESR] = 0x;
 break;
-case -2:
-/* Access rights violation */
-cs->exception_index = POWERPC_EXCP_ISI;
-if ((env->mmu_model == POWERPC_MMU_BOOKE) ||
-(env->mmu_model == POWERPC_MMU_BOOKE206)) {
-env->error_code = 0;
-} else {
-env->error_code = 0x0800;
-}
+case POWERPC_MMU_BOOKE206:
+booke206_update_mas_tlb_miss(env, eaddr, 2, mmu_idx);
+/* fall through */
+case POWERPC_MMU_BOOKE:
+cs->exception_index = POWERPC_EXCP_ITLB;
+env->error_code = 0;
+env->spr[SPR_BOOKE_DEAR] = eaddr;
+env->spr[SPR_BOOKE_ESR] = mmubooke206_esr(mmu_idx, 
MMU_DATA_LOAD);
 break;
-case -3:
-/* No execute protection violation */
-if ((env->mmu_model == POWERPC_MMU_BOOKE) ||
-(env->mmu_model == POWERPC_MMU_BOOKE206)) {
-env->spr[SPR_BOOKE_ESR] = 0x;
-env->error_code = 0;
+case POWERPC_MMU_REAL:
+cpu_abort(cs, "PowerPC in real mode should never raise "
+  "any MMU exceptions\n");
+default:
+cpu_abort(cs, "Unknown or invalid MMU model\n");
+}
+break;
+case -2:
+/* Access rights violation */
+cs->exception_index = POWERPC_EXCP_ISI;
+if ((env->mmu_model == POWERPC_MMU_BOOKE) ||
+(env->mmu_model == POWERPC_MMU_BOOKE206)) {
+env->error_code = 0;
+} else {
+env->error_code = 0x0800;
+}
+break;
+case -3:
+/* No execute protection violation */
+if ((env->mmu_model == 

[PATCH v7 30/61] target/ppc: Split off common embedded TLB init

2024-05-12 Thread BALATON Zoltan
Several 4xx CPUs and e200 share the same TLB settings enclosed in an
ifdef. Split it off in a common function to reduce code duplication
and the number of ifdefs.

Signed-off-by: BALATON Zoltan 
Reviewed-by: Nicholas Piggin 
---
 target/ppc/cpu_init.c | 46 ---
 1 file changed, 17 insertions(+), 29 deletions(-)

diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c
index 07ad788e54..92c71b2a09 100644
--- a/target/ppc/cpu_init.c
+++ b/target/ppc/cpu_init.c
@@ -2107,18 +2107,22 @@ static int check_pow_hid0_74xx(CPUPPCState *env)
 return 0;
 }
 
+static void init_tlbs_emb(CPUPPCState *env)
+{
+#ifndef CONFIG_USER_ONLY
+env->nb_tlb = 64;
+env->nb_ways = 1;
+env->tlb_type = TLB_EMB;
+#endif
+}
+
 static void init_proc_405(CPUPPCState *env)
 {
 register_40x_sprs(env);
 register_405_sprs(env);
 register_usprgh_sprs(env);
 
-/* Memory management */
-#if !defined(CONFIG_USER_ONLY)
-env->nb_tlb = 64;
-env->nb_ways = 1;
-env->tlb_type = TLB_EMB;
-#endif
+init_tlbs_emb(env);
 init_excp_4xx(env);
 env->dcache_line_size = 32;
 env->icache_line_size = 32;
@@ -2185,12 +2189,8 @@ static void init_proc_440EP(CPUPPCState *env)
  SPR_NOACCESS, SPR_NOACCESS,
  _read_generic, _write_generic,
  0x);
-/* Memory management */
-#if !defined(CONFIG_USER_ONLY)
-env->nb_tlb = 64;
-env->nb_ways = 1;
-env->tlb_type = TLB_EMB;
-#endif
+
+init_tlbs_emb(env);
 init_excp_BookE(env);
 env->dcache_line_size = 32;
 env->icache_line_size = 32;
@@ -2282,12 +2282,7 @@ static void init_proc_440GP(CPUPPCState *env)
 register_440_sprs(env);
 register_usprgh_sprs(env);
 
-/* Memory management */
-#if !defined(CONFIG_USER_ONLY)
-env->nb_tlb = 64;
-env->nb_ways = 1;
-env->tlb_type = TLB_EMB;
-#endif
+init_tlbs_emb(env);
 init_excp_BookE(env);
 env->dcache_line_size = 32;
 env->icache_line_size = 32;
@@ -2355,12 +2350,8 @@ static void init_proc_440x5(CPUPPCState *env)
  SPR_NOACCESS, SPR_NOACCESS,
  _read_generic, _write_generic,
  0x);
-/* Memory management */
-#if !defined(CONFIG_USER_ONLY)
-env->nb_tlb = 64;
-env->nb_ways = 1;
-env->tlb_type = TLB_EMB;
-#endif
+
+init_tlbs_emb(env);
 init_excp_BookE(env);
 env->dcache_line_size = 32;
 env->icache_line_size = 32;
@@ -2717,11 +2708,8 @@ static void init_proc_e200(CPUPPCState *env)
  SPR_NOACCESS, SPR_NOACCESS,
  _read_generic, _write_generic,
  0x);
-#if !defined(CONFIG_USER_ONLY)
-env->nb_tlb = 64;
-env->nb_ways = 1;
-env->tlb_type = TLB_EMB;
-#endif
+
+init_tlbs_emb(env);
 init_excp_e200(env, 0xUL);
 env->dcache_line_size = 32;
 env->icache_line_size = 32;
-- 
2.30.9




[PATCH v7 53/61] target/ppc/mmu_common.c: Init variable in function that relies on it

2024-05-12 Thread BALATON Zoltan
The ppc6xx_tlb_check() relies on the caller to initialise raddr field
in ctx. Move this init from the only caller into the function.

Signed-off-by: BALATON Zoltan 
---
 target/ppc/mmu_common.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/target/ppc/mmu_common.c b/target/ppc/mmu_common.c
index 3d028a2008..ccc1c76a06 100644
--- a/target/ppc/mmu_common.c
+++ b/target/ppc/mmu_common.c
@@ -102,6 +102,8 @@ static int ppc6xx_tlb_check(CPUPPCState *env,
 int nr, best, way, ret;
 bool is_code = (access_type == MMU_INST_FETCH);
 
+/* Initialize real address with an invalid value */
+ctx->raddr = (hwaddr)-1ULL;
 best = -1;
 ret = -1; /* No TLB found */
 for (way = 0; way < env->nb_ways; way++) {
@@ -340,8 +342,6 @@ static int mmu6xx_get_physical_address(CPUPPCState *env, 
mmu_ctx_t *ctx,
   ppc_hash32_hpt_base(cpu), ppc_hash32_hpt_mask(cpu), 
hash);
 *hashp = hash;
 
-/* Initialize real address with an invalid value */
-ctx->raddr = (hwaddr)-1ULL;
 /* Software TLB search */
 return ppc6xx_tlb_check(env, ctx, eaddr, access_type, ptem, nx);
 }
-- 
2.30.9




[PATCH v7 06/61] target/ppc/mmu_common.c: Drop cases for unimplemented MPC8xx MMU

2024-05-12 Thread BALATON Zoltan
Drop MPC8xx cases from get_physical_address_wtlb() and ppc_jumbo_xlate().
The default case would still catch this and abort the same way and
there is still a warning about it in ppc_tlb_invalidate_all() which is
called in ppc_cpu_reset_hold() so likely we never get here but to make
sure add a case to ppc_xlate() to the same effect.

Signed-off-by: BALATON Zoltan 
Reviewed-by: Nicholas Piggin 
---
 target/ppc/mmu_common.c | 12 ++--
 1 file changed, 2 insertions(+), 10 deletions(-)

diff --git a/target/ppc/mmu_common.c b/target/ppc/mmu_common.c
index 886fb6a657..3391df61cb 100644
--- a/target/ppc/mmu_common.c
+++ b/target/ppc/mmu_common.c
@@ -1219,10 +1219,6 @@ int get_physical_address_wtlb(CPUPPCState *env, 
mmu_ctx_t *ctx,
 ret = mmubooke206_get_physical_address(env, ctx, eaddr, access_type,
mmu_idx);
 break;
-case POWERPC_MMU_MPC8xx:
-/* XXX: TODO */
-cpu_abort(env_cpu(env), "MPC8xx MMU model is not implemented\n");
-break;
 case POWERPC_MMU_REAL:
 if (real_mode) {
 ret = check_physical(env, ctx, eaddr, access_type);
@@ -1353,8 +1349,6 @@ static bool ppc_jumbo_xlate(PowerPCCPU *cpu, vaddr eaddr,
 env->spr[SPR_BOOKE_DEAR] = eaddr;
 env->spr[SPR_BOOKE_ESR] = mmubooke206_esr(mmu_idx, 
MMU_DATA_LOAD);
 break;
-case POWERPC_MMU_MPC8xx:
-cpu_abort(cs, "MPC8xx MMU model is not implemented\n");
 case POWERPC_MMU_REAL:
 cpu_abort(cs, "PowerPC in real mode should never raise "
   "any MMU exceptions\n");
@@ -1427,9 +1421,6 @@ static bool ppc_jumbo_xlate(PowerPCCPU *cpu, vaddr eaddr,
 env->spr[SPR_40x_ESR] = 0x;
 }
 break;
-case POWERPC_MMU_MPC8xx:
-/* XXX: TODO */
-cpu_abort(cs, "MPC8xx MMU model is not implemented\n");
 case POWERPC_MMU_BOOKE206:
 booke206_update_mas_tlb_miss(env, eaddr, access_type, 
mmu_idx);
 /* fall through */
@@ -1539,7 +1530,8 @@ bool ppc_xlate(PowerPCCPU *cpu, vaddr eaddr, 
MMUAccessType access_type,
 case POWERPC_MMU_32B:
 return ppc_hash32_xlate(cpu, eaddr, access_type, raddrp,
psizep, protp, mmu_idx, guest_visible);
-
+case POWERPC_MMU_MPC8xx:
+cpu_abort(env_cpu(>env), "MPC8xx MMU model is not implemented\n");
 default:
 return ppc_jumbo_xlate(cpu, eaddr, access_type, raddrp,
psizep, protp, mmu_idx, guest_visible);
-- 
2.30.9




[PATCH v7 49/61] target/ppc/mmu_common.c: Inline and remove ppc6xx_tlb_pte_check()

2024-05-12 Thread BALATON Zoltan
This function is only called once and we can make the caller simpler
by inlining it.

Signed-off-by: BALATON Zoltan 
---
 target/ppc/mmu_common.c | 71 +
 1 file changed, 22 insertions(+), 49 deletions(-)

diff --git a/target/ppc/mmu_common.c b/target/ppc/mmu_common.c
index f38a73464f..a4bb8c8c3e 100644
--- a/target/ppc/mmu_common.c
+++ b/target/ppc/mmu_common.c
@@ -91,33 +91,6 @@ int ppc6xx_tlb_getnum(CPUPPCState *env, target_ulong eaddr,
 return nr;
 }
 
-static int ppc6xx_tlb_pte_check(mmu_ctx_t *ctx, target_ulong pte0,
-target_ulong pte1, int pteh,
-MMUAccessType access_type, bool nx)
-{
-/* Check validity and table match */
-if (!pte_is_valid(pte0) || ((pte0 >> 6) & 1) != pteh ||
-(pte0 & PTE_PTEM_MASK) != ctx->ptem) {
-return -1;
-}
-/* all matches should have equal RPN, WIMG & PP */
-if (ctx->raddr != (hwaddr)-1ULL &&
-(ctx->raddr & PTE_CHECK_MASK) != (pte1 & PTE_CHECK_MASK)) {
-qemu_log_mask(CPU_LOG_MMU, "Bad RPN/WIMG/PP\n");
-return -3;
-}
-/* Keep the matching PTE information */
-ctx->raddr = pte1;
-ctx->prot = ppc_hash32_pp_prot(ctx->key, pte1 & HPTE32_R_PP, nx);
-if (check_prot_access_type(ctx->prot, access_type)) {
-qemu_log_mask(CPU_LOG_MMU, "PTE access granted !\n");
-return 0;
-} else {
-qemu_log_mask(CPU_LOG_MMU, "PTE access rejected\n");
-return -2;
-}
-}
-
 /* Software driven TLB helpers */
 
 static int ppc6xx_tlb_check(CPUPPCState *env,
@@ -149,32 +122,32 @@ static int ppc6xx_tlb_check(CPUPPCState *env,
   tlb->EPN, eaddr, tlb->pte1,
   access_type == MMU_DATA_STORE ? 'S' : 'L',
   access_type == MMU_INST_FETCH ? 'I' : 'D');
-switch (ppc6xx_tlb_pte_check(ctx, tlb->pte0, tlb->pte1,
- 0, access_type, nx)) {
-case -2:
-/* Access violation */
-ret = -2;
-best = nr;
-break;
-case -1: /* No match */
-case -3: /* TLB inconsistency */
-default:
-break;
-case 0:
-/* access granted */
-/*
- * XXX: we should go on looping to check all TLBs
- *  consistency but we can speed-up the whole thing as
- *  the result would be undefined if TLBs are not
- *  consistent.
- */
+/* Check validity and table match */
+if (!pte_is_valid(tlb->pte0) || ((tlb->pte0 >> 6) & 1) != 0 ||
+(tlb->pte0 & PTE_PTEM_MASK) != ctx->ptem) {
+continue;
+}
+/* all matches should have equal RPN, WIMG & PP */
+if (ctx->raddr != (hwaddr)-1ULL &&
+(ctx->raddr & PTE_CHECK_MASK) != (tlb->pte1 & PTE_CHECK_MASK)) {
+qemu_log_mask(CPU_LOG_MMU, "Bad RPN/WIMG/PP\n");
+/* TLB inconsistency */
+continue;
+}
+/* Keep the matching PTE information */
+best = nr;
+ctx->raddr = tlb->pte1;
+ctx->prot = ppc_hash32_pp_prot(ctx->key, tlb->pte1 & HPTE32_R_PP, nx);
+if (check_prot_access_type(ctx->prot, access_type)) {
+qemu_log_mask(CPU_LOG_MMU, "PTE access granted !\n");
 ret = 0;
-best = nr;
-goto done;
+break;
+} else {
+qemu_log_mask(CPU_LOG_MMU, "PTE access rejected\n");
+ret = -2;
 }
 }
 if (best != -1) {
-done:
 qemu_log_mask(CPU_LOG_MMU, "found TLB at addr " HWADDR_FMT_plx
   " prot=%01x ret=%d\n",
   ctx->raddr & TARGET_PAGE_MASK, ctx->prot, ret);
-- 
2.30.9




[PATCH v7 27/61] target/ppc/mmu_common.c: Move mmu_ctx_t type to mmu_common.c

2024-05-12 Thread BALATON Zoltan
Remove mmu_ctx_t definition from internal.h as this type is only used
within mmu_common.c.

Signed-off-by: BALATON Zoltan 
Reviewed-by: Nicholas Piggin 
---
 target/ppc/internal.h   | 12 
 target/ppc/mmu_common.c | 11 +++
 2 files changed, 11 insertions(+), 12 deletions(-)

diff --git a/target/ppc/internal.h b/target/ppc/internal.h
index 4a4f9b9ec8..4a90dd2584 100644
--- a/target/ppc/internal.h
+++ b/target/ppc/internal.h
@@ -257,8 +257,6 @@ static inline int prot_for_access_type(MMUAccessType 
access_type)
 
 /* PowerPC MMU emulation */
 
-typedef struct mmu_ctx_t mmu_ctx_t;
-
 bool ppc_xlate(PowerPCCPU *cpu, vaddr eaddr, MMUAccessType access_type,
   hwaddr *raddrp, int *psizep, int *protp,
   int mmu_idx, bool guest_visible);
@@ -266,16 +264,6 @@ bool ppc_xlate(PowerPCCPU *cpu, vaddr eaddr, MMUAccessType 
access_type,
 /* Software driven TLB helpers */
 int ppc6xx_tlb_getnum(CPUPPCState *env, target_ulong eaddr,
 int way, int is_code);
-/* Context used internally during MMU translations */
-struct mmu_ctx_t {
-hwaddr raddr;  /* Real address  */
-hwaddr eaddr;  /* Effective address */
-int prot;  /* Protection bits   */
-hwaddr hash[2];/* Pagetable hash values */
-target_ulong ptem; /* Virtual segment ID | API  */
-int key;   /* Access key*/
-int nx;/* Non-execute area  */
-};
 
 #endif /* !CONFIG_USER_ONLY */
 
diff --git a/target/ppc/mmu_common.c b/target/ppc/mmu_common.c
index 961062bca1..34200d9cb1 100644
--- a/target/ppc/mmu_common.c
+++ b/target/ppc/mmu_common.c
@@ -36,6 +36,17 @@
 
 /* #define DUMP_PAGE_TABLES */
 
+/* Context used internally during MMU translations */
+typedef struct {
+hwaddr raddr;  /* Real address */
+hwaddr eaddr;  /* Effective address*/
+int prot;  /* Protection bits  */
+hwaddr hash[2];/* Pagetable hash values*/
+target_ulong ptem; /* Virtual segment ID | API */
+int key;   /* Access key   */
+int nx;/* Non-execute area */
+} mmu_ctx_t;
+
 void ppc_store_sdr1(CPUPPCState *env, target_ulong value)
 {
 PowerPCCPU *cpu = env_archcpu(env);
-- 
2.30.9




[PATCH v7 31/61] target/ppc/mmu-hash32.c: Drop a local variable

2024-05-12 Thread BALATON Zoltan
In ppc_hash32_xlate() the value of need_prop is checked in two places
but precalculating it does not help because when we reach the first
check we always return and not reach the second place so the value
will only be used once. We can drop the local variable and calculate
it when needed, which makes these checks using it similar to other
places with such checks.

Signed-off-by: BALATON Zoltan 
Reviewed-by: Nicholas Piggin 
---
 target/ppc/mmu-hash32.c | 7 ++-
 1 file changed, 2 insertions(+), 5 deletions(-)

diff --git a/target/ppc/mmu-hash32.c b/target/ppc/mmu-hash32.c
index da6e8b293c..3abaf16e78 100644
--- a/target/ppc/mmu-hash32.c
+++ b/target/ppc/mmu-hash32.c
@@ -386,7 +386,6 @@ bool ppc_hash32_xlate(PowerPCCPU *cpu, vaddr eaddr, 
MMUAccessType access_type,
 hwaddr pte_offset;
 ppc_hash_pte32_t pte;
 int prot;
-int need_prot;
 hwaddr raddr;
 
 /* There are no hash32 large pages. */
@@ -400,13 +399,11 @@ bool ppc_hash32_xlate(PowerPCCPU *cpu, vaddr eaddr, 
MMUAccessType access_type,
 return true;
 }
 
-need_prot = prot_for_access_type(access_type);
-
 /* 2. Check Block Address Translation entries (BATs) */
 if (env->nb_BATs != 0) {
 raddr = ppc_hash32_bat_lookup(cpu, eaddr, access_type, protp, mmu_idx);
 if (raddr != -1) {
-if (need_prot & ~*protp) {
+if (prot_for_access_type(access_type) & ~*protp) {
 if (guest_visible) {
 if (access_type == MMU_INST_FETCH) {
 cs->exception_index = POWERPC_EXCP_ISI;
@@ -474,7 +471,7 @@ bool ppc_hash32_xlate(PowerPCCPU *cpu, vaddr eaddr, 
MMUAccessType access_type,
 
 prot = ppc_hash32_pte_prot(mmu_idx, sr, pte);
 
-if (need_prot & ~prot) {
+if (prot_for_access_type(access_type) & ~prot) {
 /* Access right violation */
 qemu_log_mask(CPU_LOG_MMU, "PTE access rejected\n");
 if (guest_visible) {
-- 
2.30.9




[PATCH v7 42/61] target/ppc/mmu_common.c: Simplify ppc6xx_tlb_pte_check()

2024-05-12 Thread BALATON Zoltan
Invert conditions to avoid deep nested ifs and return early instead.
Remove some obvious comments that don't add more clarity.

Signed-off-by: BALATON Zoltan 
---
 target/ppc/mmu_common.c | 44 ++---
 1 file changed, 19 insertions(+), 25 deletions(-)

diff --git a/target/ppc/mmu_common.c b/target/ppc/mmu_common.c
index a035cefcad..564fcc7cfb 100644
--- a/target/ppc/mmu_common.c
+++ b/target/ppc/mmu_common.c
@@ -99,32 +99,26 @@ static int ppc6xx_tlb_pte_check(mmu_ctx_t *ctx, 
target_ulong pte0,
 MMUAccessType access_type)
 {
 /* Check validity and table match */
-if (pte_is_valid(pte0) && ((pte0 >> 6) & 1) == pteh) {
-/* Check vsid & api */
-if ((pte0 & PTE_PTEM_MASK) == ctx->ptem) {
-if (ctx->raddr != (hwaddr)-1ULL) {
-/* all matches should have equal RPN, WIMG & PP */
-if ((ctx->raddr & PTE_CHECK_MASK) != (pte1 & PTE_CHECK_MASK)) {
-qemu_log_mask(CPU_LOG_MMU, "Bad RPN/WIMG/PP\n");
-return -3;
-}
-}
-/* Keep the matching PTE information */
-ctx->raddr = pte1;
-ctx->prot = ppc_hash32_pp_prot(ctx->key, pte1 & HPTE32_R_PP,
-   ctx->nx);
-if (check_prot_access_type(ctx->prot, access_type)) {
-/* Access granted */
-qemu_log_mask(CPU_LOG_MMU, "PTE access granted !\n");
-return 0;
-} else {
-/* Access right violation */
-qemu_log_mask(CPU_LOG_MMU, "PTE access rejected\n");
-return -2;
-}
-}
+if (!pte_is_valid(pte0) || ((pte0 >> 6) & 1) != pteh ||
+(pte0 & PTE_PTEM_MASK) != ctx->ptem) {
+return -1;
+}
+/* all matches should have equal RPN, WIMG & PP */
+if (ctx->raddr != (hwaddr)-1ULL &&
+(ctx->raddr & PTE_CHECK_MASK) != (pte1 & PTE_CHECK_MASK)) {
+qemu_log_mask(CPU_LOG_MMU, "Bad RPN/WIMG/PP\n");
+return -3;
+}
+/* Keep the matching PTE information */
+ctx->raddr = pte1;
+ctx->prot = ppc_hash32_pp_prot(ctx->key, pte1 & HPTE32_R_PP, ctx->nx);
+if (check_prot_access_type(ctx->prot, access_type)) {
+qemu_log_mask(CPU_LOG_MMU, "PTE access granted !\n");
+return 0;
+} else {
+qemu_log_mask(CPU_LOG_MMU, "PTE access rejected\n");
+return -2;
 }
-return -1;
 }
 
 /* Software driven TLB helpers */
-- 
2.30.9




[PATCH v7 09/61] target/ppc/mmu_common.c: Move some debug logging

2024-05-12 Thread BALATON Zoltan
Move the debug logging within ppc6xx_tlb_check() from after its only
call to simplify the caller.

Signed-off-by: BALATON Zoltan 
Reviewed-by: Nicholas Piggin 
---
 target/ppc/mmu_common.c | 54 ++---
 1 file changed, 24 insertions(+), 30 deletions(-)

diff --git a/target/ppc/mmu_common.c b/target/ppc/mmu_common.c
index ba60b4902b..89bfd9aa45 100644
--- a/target/ppc/mmu_common.c
+++ b/target/ppc/mmu_common.c
@@ -225,17 +225,14 @@ static int ppc6xx_tlb_check(CPUPPCState *env, mmu_ctx_t 
*ctx,
   access_type == MMU_INST_FETCH ? 'I' : 'D');
 switch (ppc6xx_tlb_pte_check(ctx, tlb->pte0, tlb->pte1,
  0, access_type)) {
-case -3:
-/* TLB inconsistency */
-return -1;
 case -2:
 /* Access violation */
 ret = -2;
 best = nr;
 break;
-case -1:
+case -1: /* No match */
+case -3: /* TLB inconsistency */
 default:
-/* No match */
 break;
 case 0:
 /* access granted */
@@ -251,14 +248,34 @@ static int ppc6xx_tlb_check(CPUPPCState *env, mmu_ctx_t 
*ctx,
 }
 }
 if (best != -1) {
-done:
+done:
 qemu_log_mask(CPU_LOG_MMU, "found TLB at addr " HWADDR_FMT_plx
   " prot=%01x ret=%d\n",
   ctx->raddr & TARGET_PAGE_MASK, ctx->prot, ret);
 /* Update page flags */
 pte_update_flags(ctx, >tlb.tlb6[best].pte1, ret, access_type);
 }
-
+#if defined(DUMP_PAGE_TABLES)
+if (qemu_loglevel_mask(CPU_LOG_MMU)) {
+CPUState *cs = env_cpu(env);
+hwaddr base = ppc_hash32_hpt_base(env_archcpu(env));
+hwaddr len = ppc_hash32_hpt_mask(env_archcpu(env)) + 0x80;
+uint32_t a0, a1, a2, a3;
+
+qemu_log("Page table: " HWADDR_FMT_plx " len " HWADDR_FMT_plx "\n",
+ base, len);
+for (hwaddr curaddr = base; curaddr < base + len; curaddr += 16) {
+a0 = ldl_phys(cs->as, curaddr);
+a1 = ldl_phys(cs->as, curaddr + 4);
+a2 = ldl_phys(cs->as, curaddr + 8);
+a3 = ldl_phys(cs->as, curaddr + 12);
+if (a0 != 0 || a1 != 0 || a2 != 0 || a3 != 0) {
+qemu_log(HWADDR_FMT_plx ": %08x %08x %08x %08x\n",
+ curaddr, a0, a1, a2, a3);
+}
+}
+}
+#endif
 return ret;
 }
 
@@ -420,29 +437,6 @@ static int mmu6xx_get_physical_address(CPUPPCState *env, 
mmu_ctx_t *ctx,
 ctx->raddr = (hwaddr)-1ULL;
 /* Software TLB search */
 ret = ppc6xx_tlb_check(env, ctx, eaddr, access_type);
-#if defined(DUMP_PAGE_TABLES)
-if (qemu_loglevel_mask(CPU_LOG_MMU)) {
-CPUState *cs = env_cpu(env);
-hwaddr curaddr;
-uint32_t a0, a1, a2, a3;
-
-qemu_log("Page table: " HWADDR_FMT_plx " len " HWADDR_FMT_plx "\n",
- ppc_hash32_hpt_base(cpu), ppc_hash32_hpt_mask(cpu) + 
0x80);
-for (curaddr = ppc_hash32_hpt_base(cpu);
- curaddr < (ppc_hash32_hpt_base(cpu)
-+ ppc_hash32_hpt_mask(cpu) + 0x80);
- curaddr += 16) {
-a0 = ldl_phys(cs->as, curaddr);
-a1 = ldl_phys(cs->as, curaddr + 4);
-a2 = ldl_phys(cs->as, curaddr + 8);
-a3 = ldl_phys(cs->as, curaddr + 12);
-if (a0 != 0 || a1 != 0 || a2 != 0 || a3 != 0) {
-qemu_log(HWADDR_FMT_plx ": %08x %08x %08x %08x\n",
- curaddr, a0, a1, a2, a3);
-}
-}
-}
-#endif
 } else {
 qemu_log_mask(CPU_LOG_MMU, "direct store...\n");
 /* Direct-store segment : absolutely *BUGGY* for now */
-- 
2.30.9




[PATCH v7 18/61] target/ppc/mmu_common.c: Don't use mmu_ctx_t in mmubooke_get_physical_address()

2024-05-12 Thread BALATON Zoltan
mmubooke_get_physical_address() only uses the raddr and prot fields
from mmu_ctx_t. Pass these directly instead of using a ctx struct.

Signed-off-by: BALATON Zoltan 
Reviewed-by: Nicholas Piggin 
---
 target/ppc/mmu_common.c | 30 ++
 1 file changed, 10 insertions(+), 20 deletions(-)

diff --git a/target/ppc/mmu_common.c b/target/ppc/mmu_common.c
index adce6cceb8..12dac9e63a 100644
--- a/target/ppc/mmu_common.c
+++ b/target/ppc/mmu_common.c
@@ -634,36 +634,25 @@ static int mmubooke_check_tlb(CPUPPCState *env, 
ppcemb_tlb_t *tlb,
 return access_type == MMU_INST_FETCH ? -3 : -2;
 }
 
-static int mmubooke_get_physical_address(CPUPPCState *env, mmu_ctx_t *ctx,
- target_ulong address,
+static int mmubooke_get_physical_address(CPUPPCState *env, hwaddr *raddr,
+ int *prot, target_ulong address,
  MMUAccessType access_type)
 {
 ppcemb_tlb_t *tlb;
-hwaddr raddr;
-int i, ret;
+int i, ret = -1;
 
-ret = -1;
-raddr = (hwaddr)-1ULL;
 for (i = 0; i < env->nb_tlb; i++) {
 tlb = >tlb.tlbe[i];
-ret = mmubooke_check_tlb(env, tlb, , >prot, address,
+ret = mmubooke_check_tlb(env, tlb, raddr, prot, address,
  access_type, i);
 if (ret != -1) {
 break;
 }
 }
-
-if (ret >= 0) {
-ctx->raddr = raddr;
-qemu_log_mask(CPU_LOG_MMU, "%s: access granted " TARGET_FMT_lx
-  " => " HWADDR_FMT_plx " %d %d\n", __func__,
-  address, ctx->raddr, ctx->prot, ret);
-} else {
- qemu_log_mask(CPU_LOG_MMU, "%s: access refused " TARGET_FMT_lx
-   " => " HWADDR_FMT_plx " %d %d\n", __func__,
-   address, raddr, ctx->prot, ret);
-}
-
+qemu_log_mask(CPU_LOG_MMU,
+  "%s: access %s " TARGET_FMT_lx " => " HWADDR_FMT_plx
+  " %d %d\n", __func__, ret < 0 ? "refused" : "granted",
+  address, ret < 0 ? -1 : *raddr, ret == -1 ? 0 : *prot, ret);
 return ret;
 }
 
@@ -1143,7 +1132,8 @@ int get_physical_address_wtlb(CPUPPCState *env, mmu_ctx_t 
*ctx,
 bool real_mode;
 
 if (env->mmu_model == POWERPC_MMU_BOOKE) {
-return mmubooke_get_physical_address(env, ctx, eaddr, access_type);
+return mmubooke_get_physical_address(env, >raddr, >prot,
+ eaddr, access_type);
 } else if (env->mmu_model == POWERPC_MMU_BOOKE206) {
 return mmubooke206_get_physical_address(env, ctx, eaddr, access_type,
 mmu_idx);
-- 
2.30.9




[PATCH v7 40/61] target/ppc/mmu_common.c: Remove yet another single use local

2024-05-12 Thread BALATON Zoltan
In ppc6xx_tlb_pte_check() the pp variable is used only once to pass it
to a function parameter with the same name. Remove the local and
inline the value. Also use named constant for the hex value to make it
clearer.

Signed-off-by: BALATON Zoltan 
---
 target/ppc/mmu_common.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/target/ppc/mmu_common.c b/target/ppc/mmu_common.c
index 7026b6a62c..0c7cbab2bc 100644
--- a/target/ppc/mmu_common.c
+++ b/target/ppc/mmu_common.c
@@ -98,13 +98,12 @@ static int ppc6xx_tlb_pte_check(mmu_ctx_t *ctx, 
target_ulong pte0,
 target_ulong pte1, int pteh,
 MMUAccessType access_type)
 {
-int ret, pp;
+int ret;
 
 ret = -1;
 /* Check validity and table match */
 if (pte_is_valid(pte0) && ((pte0 >> 6) & 1) == pteh) {
 /* Check vsid & api */
-pp = pte1 & 0x0003;
 if ((pte0 & PTE_PTEM_MASK) == ctx->ptem) {
 if (ctx->raddr != (hwaddr)-1ULL) {
 /* all matches should have equal RPN, WIMG & PP */
@@ -115,7 +114,8 @@ static int ppc6xx_tlb_pte_check(mmu_ctx_t *ctx, 
target_ulong pte0,
 }
 /* Keep the matching PTE information */
 ctx->raddr = pte1;
-ctx->prot = ppc_hash32_pp_prot(ctx->key, pp, ctx->nx);
+ctx->prot = ppc_hash32_pp_prot(ctx->key, pte1 & HPTE32_R_PP,
+   ctx->nx);
 if (check_prot_access_type(ctx->prot, access_type)) {
 /* Access granted */
 qemu_log_mask(CPU_LOG_MMU, "PTE access granted !\n");
-- 
2.30.9




[PATCH v7 28/61] target/ppc/mmu_common.c: Remove pte_update_flags()

2024-05-12 Thread BALATON Zoltan
This function is used only once, its return value is ignored and one
of its parameter is a return value from a previous call. It is better
to inline it in the caller and remove it.

Signed-off-by: BALATON Zoltan 
---
 target/ppc/mmu_common.c | 41 +
 1 file changed, 13 insertions(+), 28 deletions(-)

diff --git a/target/ppc/mmu_common.c b/target/ppc/mmu_common.c
index 34200d9cb1..4fb93cbf40 100644
--- a/target/ppc/mmu_common.c
+++ b/target/ppc/mmu_common.c
@@ -179,39 +179,14 @@ static int ppc6xx_tlb_pte_check(mmu_ctx_t *ctx, 
target_ulong pte0,
 return ret;
 }
 
-static int pte_update_flags(mmu_ctx_t *ctx, target_ulong *pte1p,
-int ret, MMUAccessType access_type)
-{
-int store = 0;
-
-/* Update page flags */
-if (!(*pte1p & 0x0100)) {
-/* Update accessed flag */
-*pte1p |= 0x0100;
-store = 1;
-}
-if (!(*pte1p & 0x0080)) {
-if (access_type == MMU_DATA_STORE && ret == 0) {
-/* Update changed flag */
-*pte1p |= 0x0080;
-store = 1;
-} else {
-/* Force page fault for first write access */
-ctx->prot &= ~PAGE_WRITE;
-}
-}
-
-return store;
-}
-
 /* Software driven TLB helpers */
 
 static int ppc6xx_tlb_check(CPUPPCState *env, mmu_ctx_t *ctx,
 target_ulong eaddr, MMUAccessType access_type)
 {
 ppc6xx_tlb_t *tlb;
-int nr, best, way;
-int ret;
+target_ulong *pte1p;
+int nr, best, way, ret;
 
 best = -1;
 ret = -1; /* No TLB found */
@@ -264,7 +239,17 @@ done:
   " prot=%01x ret=%d\n",
   ctx->raddr & TARGET_PAGE_MASK, ctx->prot, ret);
 /* Update page flags */
-pte_update_flags(ctx, >tlb.tlb6[best].pte1, ret, access_type);
+pte1p = >tlb.tlb6[best].pte1;
+*pte1p |= 0x0100; /* Update accessed flag */
+if (!(*pte1p & 0x0080)) {
+if (access_type == MMU_DATA_STORE && ret == 0) {
+/* Update changed flag */
+*pte1p |= 0x0080;
+} else {
+/* Force page fault for first write access */
+ctx->prot &= ~PAGE_WRITE;
+}
+}
 }
 #if defined(DUMP_PAGE_TABLES)
 if (qemu_loglevel_mask(CPU_LOG_MMU)) {
-- 
2.30.9




[PATCH v7 10/61] target/ppc/mmu_common.c: Eliminate ret from mmu6xx_get_physical_address()

2024-05-12 Thread BALATON Zoltan
Return directly, which is simpler than dragging a return value through
multpile if and else blocks.

Signed-off-by: BALATON Zoltan 
Reviewed-by: Nicholas Piggin 
---
 target/ppc/mmu_common.c | 84 +++--
 1 file changed, 39 insertions(+), 45 deletions(-)

diff --git a/target/ppc/mmu_common.c b/target/ppc/mmu_common.c
index 89bfd9aa45..03d9e6bfda 100644
--- a/target/ppc/mmu_common.c
+++ b/target/ppc/mmu_common.c
@@ -386,7 +386,6 @@ static int mmu6xx_get_physical_address(CPUPPCState *env, 
mmu_ctx_t *ctx,
 target_ulong vsid, sr, pgidx;
 int ds, target_page_bits;
 bool pr;
-int ret;
 
 /* First try to find a BAT entry if there are any */
 if (env->nb_BATs && get_bat_6xx_tlb(env, ctx, eaddr, access_type) == 0) {
@@ -419,7 +418,6 @@ static int mmu6xx_get_physical_address(CPUPPCState *env, 
mmu_ctx_t *ctx,
 qemu_log_mask(CPU_LOG_MMU,
 "pte segment: key=%d ds %d nx %d vsid " TARGET_FMT_lx "\n",
 ctx->key, ds, ctx->nx, vsid);
-ret = -1;
 if (!ds) {
 /* Check if instruction fetch is allowed, if needed */
 if (type == ACCESS_CODE && ctx->nx) {
@@ -436,51 +434,47 @@ static int mmu6xx_get_physical_address(CPUPPCState *env, 
mmu_ctx_t *ctx,
 /* Initialize real address with an invalid value */
 ctx->raddr = (hwaddr)-1ULL;
 /* Software TLB search */
-ret = ppc6xx_tlb_check(env, ctx, eaddr, access_type);
-} else {
-qemu_log_mask(CPU_LOG_MMU, "direct store...\n");
-/* Direct-store segment : absolutely *BUGGY* for now */
-
-switch (type) {
-case ACCESS_INT:
-/* Integer load/store : only access allowed */
-break;
-case ACCESS_CODE:
-/* No code fetch is allowed in direct-store areas */
-return -4;
-case ACCESS_FLOAT:
-/* Floating point load/store */
-return -4;
-case ACCESS_RES:
-/* lwarx, ldarx or srwcx. */
-return -4;
-case ACCESS_CACHE:
-/*
- * dcba, dcbt, dcbtst, dcbf, dcbi, dcbst, dcbz, or icbi
- *
- * Should make the instruction do no-op.  As it already do
- * no-op, it's quite easy :-)
- */
-ctx->raddr = eaddr;
-return 0;
-case ACCESS_EXT:
-/* eciwx or ecowx */
-return -4;
-default:
-qemu_log_mask(CPU_LOG_MMU, "ERROR: instruction should not need "
-  "address translation\n");
-return -4;
-}
-if ((access_type == MMU_DATA_STORE || ctx->key != 1) &&
-(access_type == MMU_DATA_LOAD || ctx->key != 0)) {
-ctx->raddr = eaddr;
-ret = 2;
-} else {
-ret = -2;
-}
+return ppc6xx_tlb_check(env, ctx, eaddr, access_type);
 }
 
-return ret;
+/* Direct-store segment : absolutely *BUGGY* for now */
+qemu_log_mask(CPU_LOG_MMU, "direct store...\n");
+switch (type) {
+case ACCESS_INT:
+/* Integer load/store : only access allowed */
+break;
+case ACCESS_CODE:
+/* No code fetch is allowed in direct-store areas */
+return -4;
+case ACCESS_FLOAT:
+/* Floating point load/store */
+return -4;
+case ACCESS_RES:
+/* lwarx, ldarx or srwcx. */
+return -4;
+case ACCESS_CACHE:
+/*
+ * dcba, dcbt, dcbtst, dcbf, dcbi, dcbst, dcbz, or icbi
+ *
+ * Should make the instruction do no-op.  As it already do
+ * no-op, it's quite easy :-)
+ */
+ctx->raddr = eaddr;
+return 0;
+case ACCESS_EXT:
+/* eciwx or ecowx */
+return -4;
+default:
+qemu_log_mask(CPU_LOG_MMU, "ERROR: instruction should not need address"
+   " translation\n");
+return -4;
+}
+if ((access_type == MMU_DATA_STORE || ctx->key != 1) &&
+(access_type == MMU_DATA_LOAD || ctx->key != 0)) {
+ctx->raddr = eaddr;
+return 2;
+}
+return -2;
 }
 
 /* Generic TLB check function for embedded PowerPC implementations */
-- 
2.30.9




[PATCH v7 55/61] target/ppc/mmu_common.c: Stop using ctx in ppc6xx_tlb_check()

2024-05-12 Thread BALATON Zoltan
Pass raddr and prot in function parameters instead.

Signed-off-by: BALATON Zoltan 
---
 target/ppc/mmu_common.c | 26 +-
 1 file changed, 13 insertions(+), 13 deletions(-)

diff --git a/target/ppc/mmu_common.c b/target/ppc/mmu_common.c
index 331e00b71c..1137ec197b 100644
--- a/target/ppc/mmu_common.c
+++ b/target/ppc/mmu_common.c
@@ -91,10 +91,9 @@ int ppc6xx_tlb_getnum(CPUPPCState *env, target_ulong eaddr,
 
 /* Software driven TLB helpers */
 
-static int ppc6xx_tlb_check(CPUPPCState *env,
-mmu_ctx_t *ctx, target_ulong eaddr,
-MMUAccessType access_type, target_ulong ptem,
-bool key, bool nx)
+static int ppc6xx_tlb_check(CPUPPCState *env, hwaddr *raddr, int *prot,
+target_ulong eaddr, MMUAccessType access_type,
+target_ulong ptem, bool key, bool nx)
 {
 ppc6xx_tlb_t *tlb;
 target_ulong *pte1p;
@@ -102,7 +101,7 @@ static int ppc6xx_tlb_check(CPUPPCState *env,
 bool is_code = (access_type == MMU_INST_FETCH);
 
 /* Initialize real address with an invalid value */
-ctx->raddr = (hwaddr)-1ULL;
+*raddr = (hwaddr)-1ULL;
 best = -1;
 ret = -1; /* No TLB found */
 for (way = 0; way < env->nb_ways; way++) {
@@ -130,17 +129,17 @@ static int ppc6xx_tlb_check(CPUPPCState *env,
 continue;
 }
 /* all matches should have equal RPN, WIMG & PP */
-if (ctx->raddr != (hwaddr)-1ULL &&
-(ctx->raddr & PTE_CHECK_MASK) != (tlb->pte1 & PTE_CHECK_MASK)) {
+if (*raddr != (hwaddr)-1ULL &&
+(*raddr & PTE_CHECK_MASK) != (tlb->pte1 & PTE_CHECK_MASK)) {
 qemu_log_mask(CPU_LOG_MMU, "Bad RPN/WIMG/PP\n");
 /* TLB inconsistency */
 continue;
 }
 /* Keep the matching PTE information */
 best = nr;
-ctx->raddr = tlb->pte1;
-ctx->prot = ppc_hash32_pp_prot(key, tlb->pte1 & HPTE32_R_PP, nx);
-if (check_prot_access_type(ctx->prot, access_type)) {
+*raddr = tlb->pte1;
+*prot = ppc_hash32_pp_prot(key, tlb->pte1 & HPTE32_R_PP, nx);
+if (check_prot_access_type(*prot, access_type)) {
 qemu_log_mask(CPU_LOG_MMU, "PTE access granted !\n");
 ret = 0;
 break;
@@ -152,7 +151,7 @@ static int ppc6xx_tlb_check(CPUPPCState *env,
 if (best != -1) {
 qemu_log_mask(CPU_LOG_MMU, "found TLB at addr " HWADDR_FMT_plx
   " prot=%01x ret=%d\n",
-  ctx->raddr & TARGET_PAGE_MASK, ctx->prot, ret);
+  *raddr & TARGET_PAGE_MASK, *prot, ret);
 /* Update page flags */
 pte1p = >tlb.tlb6[best].pte1;
 *pte1p |= 0x0100; /* Update accessed flag */
@@ -162,7 +161,7 @@ static int ppc6xx_tlb_check(CPUPPCState *env,
 *pte1p |= 0x0080;
 } else {
 /* Force page fault for first write access */
-ctx->prot &= ~PAGE_WRITE;
+*prot &= ~PAGE_WRITE;
 }
 }
 }
@@ -344,7 +343,8 @@ static int mmu6xx_get_physical_address(CPUPPCState *env, 
mmu_ctx_t *ctx,
 *hashp = hash;
 
 /* Software TLB search */
-return ppc6xx_tlb_check(env, ctx, eaddr, access_type, ptem, key, nx);
+return ppc6xx_tlb_check(env, >raddr, >prot, eaddr,
+access_type, ptem, key, nx);
 }
 
 /* Direct-store segment : absolutely *BUGGY* for now */
-- 
2.30.9




[PATCH v7 07/61] target/ppc/mmu_common.c: Introduce mmu6xx_get_physical_address()

2024-05-12 Thread BALATON Zoltan
Repurpose get_segment_6xx_tlb() to do the whole address translation
for POWERPC_MMU_SOFT_6xx MMU model by moving the BAT check there and
renaming it to match other similar functions. These are only called
once together so no need to keep these separate functions and
combining them simplifies the caller allowing further restructuring.

Signed-off-by: BALATON Zoltan 
Reviewed-by: Nicholas Piggin 
---
 target/ppc/mmu_common.c | 26 --
 1 file changed, 12 insertions(+), 14 deletions(-)

diff --git a/target/ppc/mmu_common.c b/target/ppc/mmu_common.c
index 3391df61cb..b7c07cf515 100644
--- a/target/ppc/mmu_common.c
+++ b/target/ppc/mmu_common.c
@@ -360,19 +360,23 @@ static int get_bat_6xx_tlb(CPUPPCState *env, mmu_ctx_t 
*ctx,
 return ret;
 }
 
-/* Perform segment based translation */
-static int get_segment_6xx_tlb(CPUPPCState *env, mmu_ctx_t *ctx,
-   target_ulong eaddr, MMUAccessType access_type,
-   int type)
+static int mmu6xx_get_physical_address(CPUPPCState *env, mmu_ctx_t *ctx,
+   target_ulong eaddr,
+   MMUAccessType access_type, int type)
 {
 PowerPCCPU *cpu = env_archcpu(env);
 hwaddr hash;
-target_ulong vsid;
+target_ulong vsid, sr, pgidx;
 int ds, target_page_bits;
 bool pr;
 int ret;
-target_ulong sr, pgidx;
 
+/* First try to find a BAT entry if there are any */
+if (env->nb_BATs && get_bat_6xx_tlb(env, ctx, eaddr, access_type) == 0) {
+return 0;
+}
+
+/* Perform segment based translation when no BATs matched */
 pr = FIELD_EX64(env->msr, MSR, PR);
 ctx->eaddr = eaddr;
 
@@ -1194,14 +1198,8 @@ int get_physical_address_wtlb(CPUPPCState *env, 
mmu_ctx_t *ctx,
 if (real_mode) {
 ret = check_physical(env, ctx, eaddr, access_type);
 } else {
-/* Try to find a BAT */
-if (env->nb_BATs != 0) {
-ret = get_bat_6xx_tlb(env, ctx, eaddr, access_type);
-}
-if (ret < 0) {
-/* We didn't match any BAT entry or don't have BATs */
-ret = get_segment_6xx_tlb(env, ctx, eaddr, access_type, type);
-}
+ret = mmu6xx_get_physical_address(env, ctx, eaddr, access_type,
+  type);
 }
 break;
 
-- 
2.30.9




[PATCH v7 24/61] target/ppc/mmu_common.c: Split off real mode handling from get_physical_address_wtlb()

2024-05-12 Thread BALATON Zoltan
Add ppc_real_mode_xlate() to handle real mode translation and allow
removing this case from ppc_jumbo_xlate().

Signed-off-by: BALATON Zoltan 
---
 target/ppc/mmu_common.c | 46 -
 1 file changed, 27 insertions(+), 19 deletions(-)

diff --git a/target/ppc/mmu_common.c b/target/ppc/mmu_common.c
index 8599106f75..ab912da821 100644
--- a/target/ppc/mmu_common.c
+++ b/target/ppc/mmu_common.c
@@ -1117,23 +1117,12 @@ int get_physical_address_wtlb(CPUPPCState *env, 
mmu_ctx_t *ctx,
  MMUAccessType access_type, int type,
  int mmu_idx)
 {
-bool real_mode = (type == ACCESS_CODE) ? !FIELD_EX64(env->msr, MSR, IR)
-   : !FIELD_EX64(env->msr, MSR, DR);
-if (real_mode) {
-ctx->raddr = eaddr;
-ctx->prot = PAGE_RWX;
-return 0;
-}
-
 switch (env->mmu_model) {
 case POWERPC_MMU_SOFT_6xx:
 return mmu6xx_get_physical_address(env, ctx, eaddr, access_type, type);
 case POWERPC_MMU_SOFT_4xx:
 return mmu40x_get_physical_address(env, >raddr, >prot, eaddr,
access_type);
-case POWERPC_MMU_REAL:
-cpu_abort(env_cpu(env),
-  "PowerPC in real mode do not do any translation\n");
 default:
 cpu_abort(env_cpu(env), "Unknown or invalid MMU model\n");
 }
@@ -1251,6 +1240,24 @@ static bool ppc_booke_xlate(PowerPCCPU *cpu, vaddr eaddr,
 return false;
 }
 
+static bool ppc_real_mode_xlate(PowerPCCPU *cpu, vaddr eaddr,
+MMUAccessType access_type,
+hwaddr *raddrp, int *psizep, int *protp)
+{
+CPUPPCState *env = >env;
+
+if (access_type == MMU_INST_FETCH ? !FIELD_EX64(env->msr, MSR, IR)
+  : !FIELD_EX64(env->msr, MSR, DR)) {
+*raddrp = eaddr;
+*protp = PAGE_RWX;
+*psizep = TARGET_PAGE_BITS;
+return true;
+} else if (env->mmu_model == POWERPC_MMU_REAL) {
+cpu_abort(CPU(cpu), "PowerPC in real mode shold not do translation\n");
+}
+return false;
+}
+
 /* Perform address translation */
 /* TODO: Split this by mmu_model. */
 static bool ppc_jumbo_xlate(PowerPCCPU *cpu, vaddr eaddr,
@@ -1264,6 +1271,10 @@ static bool ppc_jumbo_xlate(PowerPCCPU *cpu, vaddr eaddr,
 int type;
 int ret;
 
+if (ppc_real_mode_xlate(cpu, eaddr, access_type, raddrp, psizep, protp)) {
+return true;
+}
+
 if (access_type == MMU_INST_FETCH) {
 /* code access */
 type = ACCESS_CODE;
@@ -1303,11 +1314,8 @@ static bool ppc_jumbo_xlate(PowerPCCPU *cpu, vaddr eaddr,
 env->spr[SPR_40x_DEAR] = eaddr;
 env->spr[SPR_40x_ESR] = 0x;
 break;
-case POWERPC_MMU_REAL:
-cpu_abort(cs, "PowerPC in real mode should never raise "
-  "any MMU exceptions\n");
 default:
-cpu_abort(cs, "Unknown or invalid MMU model\n");
+g_assert_not_reached();
 }
 break;
 case -2:
@@ -1359,11 +1367,8 @@ static bool ppc_jumbo_xlate(PowerPCCPU *cpu, vaddr eaddr,
 env->spr[SPR_40x_ESR] = 0x;
 }
 break;
-case POWERPC_MMU_REAL:
-cpu_abort(cs, "PowerPC in real mode should never raise "
-  "any MMU exceptions\n");
 default:
-cpu_abort(cs, "Unknown or invalid MMU model\n");
+g_assert_not_reached();
 }
 break;
 case -2:
@@ -1457,6 +1462,9 @@ bool ppc_xlate(PowerPCCPU *cpu, vaddr eaddr, 
MMUAccessType access_type,
 case POWERPC_MMU_BOOKE206:
 return ppc_booke_xlate(cpu, eaddr, access_type, raddrp,
psizep, protp, mmu_idx, guest_visible);
+case POWERPC_MMU_REAL:
+return ppc_real_mode_xlate(cpu, eaddr, access_type, raddrp, psizep,
+   protp);
 case POWERPC_MMU_MPC8xx:
 cpu_abort(env_cpu(>env), "MPC8xx MMU model is not implemented\n");
 default:
-- 
2.30.9




[PATCH v7 26/61] target/ppc/mmu_common.c: Transform ppc_jumbo_xlate() into ppc_6xx_xlate()

2024-05-12 Thread BALATON Zoltan
Now that only 6xx cases left in ppc_jumbo_xlate() we can change it
to ppc_6xx_xlate() also removing get_physical_address_wtlb().

Signed-off-by: BALATON Zoltan 
---
 target/ppc/internal.h   |  5 +
 target/ppc/mmu_common.c | 38 --
 2 files changed, 13 insertions(+), 30 deletions(-)

diff --git a/target/ppc/internal.h b/target/ppc/internal.h
index 98b41a970c..4a4f9b9ec8 100644
--- a/target/ppc/internal.h
+++ b/target/ppc/internal.h
@@ -262,10 +262,7 @@ typedef struct mmu_ctx_t mmu_ctx_t;
 bool ppc_xlate(PowerPCCPU *cpu, vaddr eaddr, MMUAccessType access_type,
   hwaddr *raddrp, int *psizep, int *protp,
   int mmu_idx, bool guest_visible);
-int get_physical_address_wtlb(CPUPPCState *env, mmu_ctx_t *ctx,
- target_ulong eaddr,
- MMUAccessType access_type, int type,
- int mmu_idx);
+
 /* Software driven TLB helpers */
 int ppc6xx_tlb_getnum(CPUPPCState *env, target_ulong eaddr,
 int way, int is_code);
diff --git a/target/ppc/mmu_common.c b/target/ppc/mmu_common.c
index ddb014e0aa..961062bca1 100644
--- a/target/ppc/mmu_common.c
+++ b/target/ppc/mmu_common.c
@@ -1112,22 +1112,6 @@ void dump_mmu(CPUPPCState *env)
 }
 }
 
-int get_physical_address_wtlb(CPUPPCState *env, mmu_ctx_t *ctx,
- target_ulong eaddr,
- MMUAccessType access_type, int type,
- int mmu_idx)
-{
-switch (env->mmu_model) {
-case POWERPC_MMU_SOFT_6xx:
-return mmu6xx_get_physical_address(env, ctx, eaddr, access_type, type);
-case POWERPC_MMU_SOFT_4xx:
-return mmu40x_get_physical_address(env, >raddr, >prot, eaddr,
-   access_type);
-default:
-cpu_abort(env_cpu(env), "Unknown or invalid MMU model\n");
-}
-}
-
 static void booke206_update_mas_tlb_miss(CPUPPCState *env, target_ulong 
address,
  MMUAccessType access_type, int 
mmu_idx)
 {
@@ -1326,12 +1310,10 @@ static bool ppc_40x_xlate(PowerPCCPU *cpu, vaddr eaddr,
 return false;
 }
 
-/* Perform address translation */
-/* TODO: Split this by mmu_model. */
-static bool ppc_jumbo_xlate(PowerPCCPU *cpu, vaddr eaddr,
-MMUAccessType access_type,
-hwaddr *raddrp, int *psizep, int *protp,
-int mmu_idx, bool guest_visible)
+static bool ppc_6xx_xlate(PowerPCCPU *cpu, vaddr eaddr,
+  MMUAccessType access_type,
+  hwaddr *raddrp, int *psizep, int *protp,
+  int mmu_idx, bool guest_visible)
 {
 CPUState *cs = CPU(cpu);
 CPUPPCState *env = >env;
@@ -1353,8 +1335,10 @@ static bool ppc_jumbo_xlate(PowerPCCPU *cpu, vaddr eaddr,
 type = ACCESS_INT;
 }
 
-ret = get_physical_address_wtlb(env, , eaddr, access_type,
-type, mmu_idx);
+ctx.prot = 0;
+ctx.hash[0] = 0;
+ctx.hash[1] = 0;
+ret = mmu6xx_get_physical_address(env, , eaddr, access_type, type);
 if (ret == 0) {
 *raddrp = ctx.raddr;
 *protp = ctx.prot;
@@ -1498,14 +1482,16 @@ bool ppc_xlate(PowerPCCPU *cpu, vaddr eaddr, 
MMUAccessType access_type,
 case POWERPC_MMU_SOFT_4xx:
 return ppc_40x_xlate(cpu, eaddr, access_type, raddrp,
  psizep, protp, mmu_idx, guest_visible);
+case POWERPC_MMU_SOFT_6xx:
+return ppc_6xx_xlate(cpu, eaddr, access_type, raddrp,
+ psizep, protp, mmu_idx, guest_visible);
 case POWERPC_MMU_REAL:
 return ppc_real_mode_xlate(cpu, eaddr, access_type, raddrp, psizep,
protp);
 case POWERPC_MMU_MPC8xx:
 cpu_abort(env_cpu(>env), "MPC8xx MMU model is not implemented\n");
 default:
-return ppc_jumbo_xlate(cpu, eaddr, access_type, raddrp,
-   psizep, protp, mmu_idx, guest_visible);
+cpu_abort(CPU(cpu), "Unknown or invalid MMU model\n");
 }
 }
 
-- 
2.30.9




[PATCH v7 35/61] target/ppc: Remove pp_check() and reuse ppc_hash32_pp_prot()

2024-05-12 Thread BALATON Zoltan
The ppc_hash32_pp_prot() function in mmu-hash32.c is the same as
pp_check() in mmu_common.c, merge these to remove duplicated code.
Define the common function as static lnline otherwise exporting the
function from mmu-hash32.c would stop the compiler inlining it which
results in slightly lower performance.

Signed-off-by: BALATON Zoltan 
---
 target/ppc/mmu-hash32.c | 45 -
 target/ppc/mmu-hash32.h | 36 +
 target/ppc/mmu_common.c | 44 ++--
 3 files changed, 38 insertions(+), 87 deletions(-)

diff --git a/target/ppc/mmu-hash32.c b/target/ppc/mmu-hash32.c
index 1e8f1df0f0..d5f2057eb1 100644
--- a/target/ppc/mmu-hash32.c
+++ b/target/ppc/mmu-hash32.c
@@ -37,51 +37,6 @@
 #  define LOG_BATS(...) do { } while (0)
 #endif
 
-static int ppc_hash32_pp_prot(int key, int pp, int nx)
-{
-int prot;
-
-if (key == 0) {
-switch (pp) {
-case 0x0:
-case 0x1:
-case 0x2:
-prot = PAGE_READ | PAGE_WRITE;
-break;
-
-case 0x3:
-prot = PAGE_READ;
-break;
-
-default:
-abort();
-}
-} else {
-switch (pp) {
-case 0x0:
-prot = 0;
-break;
-
-case 0x1:
-case 0x3:
-prot = PAGE_READ;
-break;
-
-case 0x2:
-prot = PAGE_READ | PAGE_WRITE;
-break;
-
-default:
-abort();
-}
-}
-if (nx == 0) {
-prot |= PAGE_EXEC;
-}
-
-return prot;
-}
-
 static int ppc_hash32_pte_prot(int mmu_idx,
target_ulong sr, ppc_hash_pte32_t pte)
 {
diff --git a/target/ppc/mmu-hash32.h b/target/ppc/mmu-hash32.h
index 7119a63d97..bf99161858 100644
--- a/target/ppc/mmu-hash32.h
+++ b/target/ppc/mmu-hash32.h
@@ -102,6 +102,42 @@ static inline void ppc_hash32_store_hpte1(PowerPCCPU *cpu,
 stl_phys(CPU(cpu)->as, base + pte_offset + HASH_PTE_SIZE_32 / 2, pte1);
 }
 
+static inline int ppc_hash32_pp_prot(bool key, int pp, bool nx)
+{
+int prot;
+
+if (key) {
+switch (pp) {
+case 0x0:
+prot = 0;
+break;
+case 0x1:
+case 0x3:
+prot = PAGE_READ;
+break;
+case 0x2:
+prot = PAGE_READ | PAGE_WRITE;
+break;
+default:
+g_assert_not_reached();
+}
+} else {
+switch (pp) {
+case 0x0:
+case 0x1:
+case 0x2:
+prot = PAGE_READ | PAGE_WRITE;
+break;
+case 0x3:
+prot = PAGE_READ;
+break;
+default:
+g_assert_not_reached();
+}
+}
+return nx ? prot : prot | PAGE_EXEC;
+}
+
 typedef struct {
 uint32_t pte0, pte1;
 } ppc_hash_pte32_t;
diff --git a/target/ppc/mmu_common.c b/target/ppc/mmu_common.c
index e1462a25dd..9e0bfbda67 100644
--- a/target/ppc/mmu_common.c
+++ b/target/ppc/mmu_common.c
@@ -77,44 +77,6 @@ void ppc_store_sdr1(CPUPPCState *env, target_ulong value)
 /*/
 /* PowerPC MMU emulation */
 
-static int pp_check(int key, int pp, int nx)
-{
-int access;
-
-/* Compute access rights */
-access = 0;
-if (key == 0) {
-switch (pp) {
-case 0x0:
-case 0x1:
-case 0x2:
-access |= PAGE_WRITE;
-/* fall through */
-case 0x3:
-access |= PAGE_READ;
-break;
-}
-} else {
-switch (pp) {
-case 0x0:
-access = 0;
-break;
-case 0x1:
-case 0x3:
-access = PAGE_READ;
-break;
-case 0x2:
-access = PAGE_READ | PAGE_WRITE;
-break;
-}
-}
-if (nx == 0) {
-access |= PAGE_EXEC;
-}
-
-return access;
-}
-
 int ppc6xx_tlb_getnum(CPUPPCState *env, target_ulong eaddr,
 int way, int is_code)
 {
@@ -137,7 +99,7 @@ static int ppc6xx_tlb_pte_check(mmu_ctx_t *ctx, target_ulong 
pte0,
 MMUAccessType access_type)
 {
 target_ulong ptem, mmask;
-int access, ret, pteh, ptev, pp;
+int ret, pteh, ptev, pp;
 
 ret = -1;
 /* Check validity and table match */
@@ -156,11 +118,9 @@ static int ppc6xx_tlb_pte_check(mmu_ctx_t *ctx, 
target_ulong pte0,
 return -3;
 }
 }
-/* Compute access rights */
-access = pp_check(ctx->key, pp, ctx->nx);
 /* Keep the matching PTE information */
 ctx->raddr = pte1;
-ctx->prot = access;
+ctx->prot = ppc_hash32_pp_prot(ctx->key, pp, ctx->nx);
 if (check_prot_access_type(ctx->prot, access_type)) {
 /* Access granted */
 

[PATCH v7 20/61] target/ppc/mmu_common.c: Remove BookE from direct store handling

2024-05-12 Thread BALATON Zoltan
As BookE never returns -4 we can drop BookE from the direct store case
in ppc_jumbo_xlate().

Signed-off-by: BALATON Zoltan 
Reviewed-by: Nicholas Piggin 
---
 target/ppc/mmu_common.c | 7 +--
 1 file changed, 1 insertion(+), 6 deletions(-)

diff --git a/target/ppc/mmu_common.c b/target/ppc/mmu_common.c
index 004ea2111d..6c6c7c55b6 100644
--- a/target/ppc/mmu_common.c
+++ b/target/ppc/mmu_common.c
@@ -1298,12 +1298,7 @@ static bool ppc_jumbo_xlate(PowerPCCPU *cpu, vaddr eaddr,
 /* Direct store exception */
 /* No code fetch is allowed in direct-store areas */
 cs->exception_index = POWERPC_EXCP_ISI;
-if ((env->mmu_model == POWERPC_MMU_BOOKE) ||
-(env->mmu_model == POWERPC_MMU_BOOKE206)) {
-env->error_code = 0;
-} else {
-env->error_code = 0x1000;
-}
+env->error_code = 0x1000;
 break;
 }
 } else {
-- 
2.30.9




[PATCH v7 22/61] target/ppc/mmu_common.c: Simplify ppc_booke_xlate() part 1

2024-05-12 Thread BALATON Zoltan
Move setting error_code that appears in every case out in front and
hoist the common fall through case for BOOKE206 as well which allows
removing the nested switches.

Signed-off-by: BALATON Zoltan 
Reviewed-by: Nicholas Piggin 
---
 target/ppc/mmu_common.c | 41 -
 1 file changed, 12 insertions(+), 29 deletions(-)

diff --git a/target/ppc/mmu_common.c b/target/ppc/mmu_common.c
index 09a780bb7a..611092966b 100644
--- a/target/ppc/mmu_common.c
+++ b/target/ppc/mmu_common.c
@@ -1220,58 +1220,41 @@ static bool ppc_booke_xlate(PowerPCCPU *cpu, vaddr 
eaddr,
 }
 
 log_cpu_state_mask(CPU_LOG_MMU, cs, 0);
+env->error_code = 0;
+if (ret == -1) {
+if (env->mmu_model == POWERPC_MMU_BOOKE206) {
+booke206_update_mas_tlb_miss(env, eaddr, access_type, mmu_idx);
+}
+}
 if (access_type == MMU_INST_FETCH) {
 switch (ret) {
 case -1:
 /* No matches in page tables or TLB */
-switch (env->mmu_model) {
-case POWERPC_MMU_BOOKE206:
-booke206_update_mas_tlb_miss(env, eaddr, access_type, mmu_idx);
-/* fall through */
-case POWERPC_MMU_BOOKE:
-cs->exception_index = POWERPC_EXCP_ITLB;
-env->error_code = 0;
-env->spr[SPR_BOOKE_DEAR] = eaddr;
-env->spr[SPR_BOOKE_ESR] = mmubooke206_esr(mmu_idx, 
access_type);
-break;
-default:
-g_assert_not_reached();
-}
+cs->exception_index = POWERPC_EXCP_ITLB;
+env->spr[SPR_BOOKE_DEAR] = eaddr;
+env->spr[SPR_BOOKE_ESR] = mmubooke206_esr(mmu_idx, access_type);
 break;
 case -2:
 /* Access rights violation */
 cs->exception_index = POWERPC_EXCP_ISI;
-env->error_code = 0;
 break;
 case -3:
 /* No execute protection violation */
 cs->exception_index = POWERPC_EXCP_ISI;
 env->spr[SPR_BOOKE_ESR] = 0;
-env->error_code = 0;
 break;
 }
 } else {
 switch (ret) {
 case -1:
 /* No matches in page tables or TLB */
-switch (env->mmu_model) {
-case POWERPC_MMU_BOOKE206:
-booke206_update_mas_tlb_miss(env, eaddr, access_type, mmu_idx);
-/* fall through */
-case POWERPC_MMU_BOOKE:
-cs->exception_index = POWERPC_EXCP_DTLB;
-env->error_code = 0;
-env->spr[SPR_BOOKE_DEAR] = eaddr;
-env->spr[SPR_BOOKE_ESR] = mmubooke206_esr(mmu_idx, 
access_type);
-break;
-default:
-g_assert_not_reached();
-}
+cs->exception_index = POWERPC_EXCP_DTLB;
+env->spr[SPR_BOOKE_DEAR] = eaddr;
+env->spr[SPR_BOOKE_ESR] = mmubooke206_esr(mmu_idx, access_type);
 break;
 case -2:
 /* Access rights violation */
 cs->exception_index = POWERPC_EXCP_DSI;
-env->error_code = 0;
 env->spr[SPR_BOOKE_DEAR] = eaddr;
 env->spr[SPR_BOOKE_ESR] = mmubooke206_esr(mmu_idx, access_type);
 break;
-- 
2.30.9




[PATCH v7 02/61] target/ppc: Remove unused helper

2024-05-12 Thread BALATON Zoltan
The helper_rac function is defined but not used, remove it.

Fixes: 005b69fdcc (target/ppc: Remove PowerPC 601 CPUs)
Signed-off-by: BALATON Zoltan 
Reviwed-by: Nicholas Piggin 
---
 target/ppc/helper.h |  2 --
 target/ppc/mmu_helper.c | 24 
 2 files changed, 26 deletions(-)

diff --git a/target/ppc/helper.h b/target/ppc/helper.h
index 86f97ee1e7..f769e01c3d 100644
--- a/target/ppc/helper.h
+++ b/target/ppc/helper.h
@@ -700,8 +700,6 @@ DEF_HELPER_2(book3s_msgclr, void, env, tl)
 
 DEF_HELPER_4(dlmzb, tl, env, tl, tl, i32)
 #if !defined(CONFIG_USER_ONLY)
-DEF_HELPER_2(rac, tl, env, tl)
-
 DEF_HELPER_2(load_dcr, tl, env, tl)
 DEF_HELPER_3(store_dcr, void, env, tl, tl)
 #endif
diff --git a/target/ppc/mmu_helper.c b/target/ppc/mmu_helper.c
index b35a93c198..421e777ee6 100644
--- a/target/ppc/mmu_helper.c
+++ b/target/ppc/mmu_helper.c
@@ -596,30 +596,6 @@ void helper_6xx_tlbi(CPUPPCState *env, target_ulong EPN)
 do_6xx_tlb(env, EPN, 1);
 }
 
-/*/
-/* PowerPC 601 specific instructions (POWER bridge) */
-
-target_ulong helper_rac(CPUPPCState *env, target_ulong addr)
-{
-mmu_ctx_t ctx;
-int nb_BATs;
-target_ulong ret = 0;
-
-/*
- * We don't have to generate many instances of this instruction,
- * as rac is supervisor only.
- *
- * XXX: FIX THIS: Pretend we have no BAT
- */
-nb_BATs = env->nb_BATs;
-env->nb_BATs = 0;
-if (get_physical_address_wtlb(env, , addr, 0, ACCESS_INT, 0) == 0) {
-ret = ctx.raddr;
-}
-env->nb_BATs = nb_BATs;
-return ret;
-}
-
 static inline target_ulong booke_tlb_to_page_size(int size)
 {
 return 1024 << (2 * size);
-- 
2.30.9




[PATCH v7 01/61] target/ppc: Remove unused struct 'mmu_ctx_hash32'

2024-05-12 Thread BALATON Zoltan
From: "Dr. David Alan Gilbert" 

I think it's use was removed by
Commit 5883d8b296 ("mmu-hash*: Don't use full ppc_hash{32,
64}_translate() path for get_phys_page_debug()")

Signed-off-by: Dr. David Alan Gilbert 
Reviewed-by: BALATON Zoltan 
Signed-off-by: BALATON Zoltan 
---
 target/ppc/mmu-hash32.c | 6 --
 1 file changed, 6 deletions(-)

diff --git a/target/ppc/mmu-hash32.c b/target/ppc/mmu-hash32.c
index 6dfedab11d..da6e8b293c 100644
--- a/target/ppc/mmu-hash32.c
+++ b/target/ppc/mmu-hash32.c
@@ -37,12 +37,6 @@
 #  define LOG_BATS(...) do { } while (0)
 #endif
 
-struct mmu_ctx_hash32 {
-hwaddr raddr;  /* Real address  */
-int prot;  /* Protection bits   */
-int key;   /* Access key*/
-};
-
 static int ppc_hash32_pp_prot(int key, int pp, int nx)
 {
 int prot;
-- 
2.30.9




Re: hw/usb/hcd-ohci: Fix #1510, #303: pid not IN or OUT

2024-05-12 Thread Cord Amfmgm
On Sat, May 11, 2024 at 5:25 AM Peter Maydell 
wrote:

> On Thu, 9 May 2024 at 19:17, Cord Amfmgm  wrote:
> >
> >
> >
> > On Thu, May 9, 2024 at 12:48 PM Peter Maydell 
> wrote:
> >>
> >> On Wed, 8 May 2024 at 16:29, Cord Amfmgm  wrote:
> >> > On Wed, May 8, 2024 at 3:45 AM Thomas Huth  wrote:
> >> >>
> >> >> Your Signed-off-by line does not match the From: line ... could you
> please
> >> >> fix this? (see
> >> >>
> https://www.qemu.org/docs/master/devel/submitting-a-patch.html#patch-emails-must-include-a-signed-off-by-line
> >> >> , too)
> >> >
> >> >
> >> > I'll submit the new patch request with my pseudonym in the From: and
> Signed-off-by: lines, per your request. Doesn't matter to me. However, this
> arises simply because I don't give gmail my real name -
> https://en.wikipedia.org/wiki/Nymwars
> >>
> >> I'm confused now. Of the two names you've used in this
> >> patch (Cord Amfmgm and David Hubbard), are they both
> >> pseudonyms, or is one a pseudonym and one your real name?
> >>
> >
> > Hi Peter,
> >
> > I am attempting to submit a small patch. For context, I'm getting
> broader attention now because apparently OHCI is one of the less used
> components of qemu and maybe the review process was taking a while. That's
> relevant because I wasn't able to get prompt feedback and am now choosing
> what appears to be the most expeditious approach -- all I want is to get
> this patch done and be out of your hair. If Thomas Huth wants me to use a
> consistent name, have I not complied? Are you asking out of curiosity or is
> there a valid reason why I should answer your question in order to get the
> patch submitted? Would you like to have a friendly chat over virtual coffee
> sometime (but off-list)?
> >
> > If you could please clarify I'm sure the answer is an easy one.
>
> I'm asking because our basic expected position is "commits
> are from the submitter's actual name, not a pseudonym". Obviously
> we can't tell if people use a consistent plausible looking
> pseudonym whether that corresponds to their real-world name
> or not, but if you have a real name you're happy to attach
> to this patch and are merely using a pseudonym for Google
> email, then the resubmit of this patch didn't seem to me
> to do that. i.e. I was expecting the change to be "make the
> patch From: match the Signed-off-by line", not "make the
> Signed-off-by line match the patch From:". (For avoidance
> of doubt, we don't care about the email From: line, which
> is distinct from the commit message From: i.e. author.)
> So I was essentially asking "did you mean to do this, or did
> you misunderstand what we were asking for?".
>

I think that is what caught me off guard. I'm learning how to submit the
correctly formatted patch. I would very much like to disconnect the patch
From: from the email From: line.


> On the question of the actual patch, I'll try to get to it
> if Gerd doesn't first (though I have a conference next week
> so it might be the week after). The main thing I need to chase
> down is whether it's OK to call usb_packet_addbuf() with a
> zero length or not.
>

Good catch. I have no problem modifying the patch with better logic for a
zero length packet.


Re: [PATCH 00/45] target/hppa: Misc improvements

2024-05-12 Thread Sven Schnelle
Philippe Mathieu-Daudé  writes:

> Cc'ing Helge & Sven as I'm going to skip this series.
>
> Suggestion:
>
> -- >8 --
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 1b79767d61..be7535b55e 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -254,6 +254,8 @@ F: target/hexagon/gen_idef_parser_funcs.py
>
>  HPPA (PA-RISC) TCG CPUs
>  M: Richard Henderson 
> +R: Helge Deller 
> +R: Sven Schnelle 
>  S: Maintained
>  F: target/hppa/
>  F: disas/hppa.c
> @@ -1214,6 +1216,7 @@ HP-PARISC Machines
>  HP B160L, HP C3700
>  M: Richard Henderson 
>  R: Helge Deller 
> +R: Sven Schnelle 
>  S: Odd Fixes
>  F: configs/devices/hppa-softmmu/default.mak
>  F: hw/display/artist.c

Please don't add me as reviewer - i'm only looking in irregular
intervals at hppa tcg in qemu.



[PATCH 2/2] Fix mouse/motion event scaling issue with GTK display backend

2024-05-12 Thread hikalium
Remove gtk_widget_get_scale_factor() usage from the calculation of
the motion events in the GTK backend to make it work correctly on
environments that have `gtk_widget_get_scale_factor() != 1`.

This scale factor usage had been introduced in the commit f14aab420c and
at that time the window size was used for calculating the things and it
was working correctly. However, in the commit 2f31663ed4 the logic
switched to use the widget size instead of window size and because of
the change the usage of scale factor becomes invalid (since widgets use
`vc->gfx.scale_{x, y}` for scaling).o

Tested on Crostini on ChromeOS (15823.51.0) with an external display.

Fixes: 2f31663ed4 ("ui/gtk: use widget size for cursor motion event")
Fixes: f14aab420c ("ui: fix incorrect pointer position on highdpi with
gtk")

Signed-off-by: hikalium 
---
 ui/gtk.c | 18 +-
 1 file changed, 13 insertions(+), 5 deletions(-)

diff --git a/ui/gtk.c b/ui/gtk.c
index ebae888d4f..4386198c95 100644
--- a/ui/gtk.c
+++ b/ui/gtk.c
@@ -887,7 +887,7 @@ static gboolean gd_motion_event(GtkWidget *widget, 
GdkEventMotion *motion,
 int x, y;
 int mx, my;
 int fbh, fbw;
-int ww, wh, ws;
+int ww, wh;
 
 if (!vc->gfx.ds) {
 return TRUE;
@@ -895,11 +895,15 @@ static gboolean gd_motion_event(GtkWidget *widget, 
GdkEventMotion *motion,
 
 fbw = surface_width(vc->gfx.ds) * vc->gfx.scale_x;
 fbh = surface_height(vc->gfx.ds) * vc->gfx.scale_y;
-
 ww = gtk_widget_get_allocated_width(widget);
 wh = gtk_widget_get_allocated_height(widget);
-ws = gtk_widget_get_scale_factor(widget);
 
+/*
+ * `widget` may not have the same size with the frame buffer.
+ * In such cases, some paddings are needed around the `vc`.
+ * To achieve that, `vc` will be displayed at (mx, my)
+ * so that it is displayed at the center of the widget.
+ */
 mx = my = 0;
 if (ww > fbw) {
 mx = (ww - fbw) / 2;
@@ -908,8 +912,12 @@ static gboolean gd_motion_event(GtkWidget *widget, 
GdkEventMotion *motion,
 my = (wh - fbh) / 2;
 }
 
-x = (motion->x - mx) / vc->gfx.scale_x * ws;
-y = (motion->y - my) / vc->gfx.scale_y * ws;
+/*
+ * `motion` is reported in `widget` coordinates
+ * so translating it to the coordinates in `vc`.
+ */
+x = (motion->x - mx) / vc->gfx.scale_x;
+y = (motion->y - my) / vc->gfx.scale_y;
 
 trace_gd_motion_event(ww, wh, gtk_widget_get_scale_factor(widget), x, y);
 
-- 
2.39.2




[PATCH 1/2] Add gd_motion_event trace event

2024-05-12 Thread hikalium
Add gd_motion_event trace event for making it easy to debug
gd_motion_event related issues.

Signed-off-by: hikalium 
---
 ui/gtk.c| 2 ++
 ui/trace-events | 1 +
 2 files changed, 3 insertions(+)

diff --git a/ui/gtk.c b/ui/gtk.c
index 810d7fc796..ebae888d4f 100644
--- a/ui/gtk.c
+++ b/ui/gtk.c
@@ -911,6 +911,8 @@ static gboolean gd_motion_event(GtkWidget *widget, 
GdkEventMotion *motion,
 x = (motion->x - mx) / vc->gfx.scale_x * ws;
 y = (motion->y - my) / vc->gfx.scale_y * ws;
 
+trace_gd_motion_event(ww, wh, gtk_widget_get_scale_factor(widget), x, y);
+
 if (qemu_input_is_absolute(vc->gfx.dcl.con)) {
 if (x < 0 || y < 0 ||
 x >= surface_width(vc->gfx.ds) ||
diff --git a/ui/trace-events b/ui/trace-events
index e6a2894303..69ff22955d 100644
--- a/ui/trace-events
+++ b/ui/trace-events
@@ -28,6 +28,7 @@ gd_ungrab(const char *tab, const char *device) "tab=%s, 
dev=%s"
 gd_keymap_windowing(const char *name) "backend=%s"
 gd_gl_area_create_context(void *ctx, int major, int minor) "ctx=%p, major=%d, 
minor=%d"
 gd_gl_area_destroy_context(void *ctx, void *current_ctx) "ctx=%p, 
current_ctx=%p"
+gd_motion_event(int ww, int wh, int ws, int x, int y) "ww=%d, wh=%d, ws=%d, 
x=%d, y=%d"
 
 # vnc-auth-sasl.c
 # vnc-auth-vencrypt.c
-- 
2.39.2




[PATCH] hw/mips/loongson3_virt: Implement node counter timer

2024-05-12 Thread Jiaxun Yang
Node counter is a timer presents on Loongson-3 chips, which runs
as fast as CPU clock. It's being mapped into a MMIO location.

Emulate this for loongson3_virt machine, in hope that kernel can
use it as a better clock source.

Hardware's behavior on 32-bit read/write is also emulated in case
legacy kernel is trying to use it with hi/lo splitted read.

Signed-off-by: Jiaxun Yang 
---
 hw/mips/loongson3_bootp.h |  1 +
 hw/mips/loongson3_virt.c  | 38 ++
 2 files changed, 35 insertions(+), 4 deletions(-)

diff --git a/hw/mips/loongson3_bootp.h b/hw/mips/loongson3_bootp.h
index 1b0dd3b59171..c6a435397d2c 100644
--- a/hw/mips/loongson3_bootp.h
+++ b/hw/mips/loongson3_bootp.h
@@ -210,6 +210,7 @@ enum {
 VIRT_PCIE_ECAM,
 VIRT_BIOS_ROM,
 VIRT_UART,
+VIRT_NODECNT,
 VIRT_LIOINTC,
 VIRT_PCIE_MMIO,
 VIRT_HIGHMEM
diff --git a/hw/mips/loongson3_virt.c b/hw/mips/loongson3_virt.c
index b10a611a98f4..b78ac8032096 100644
--- a/hw/mips/loongson3_virt.c
+++ b/hw/mips/loongson3_virt.c
@@ -74,6 +74,7 @@ const MemMapEntry virt_memmap[] = {
 [VIRT_PCIE_ECAM] =   { 0x1a00, 0x200 },
 [VIRT_BIOS_ROM] ={ 0x1fc0,  0x20 },
 [VIRT_UART] ={ 0x1fe001e0,   0x8 },
+[VIRT_NODECNT] = { 0x3ff00408,   0x8 },
 [VIRT_LIOINTC] = { 0x3ff01400,  0x64 },
 [VIRT_PCIE_MMIO] =   { 0x4000,0x4000 },
 [VIRT_HIGHMEM] = { 0x8000,   0x0 }, /* Variable */
@@ -92,6 +93,7 @@ static const MemMapEntry loader_rommap[] = {
 
 struct LoongsonMachineState {
 MachineState parent_obj;
+Clock *cpuclk;
 MemoryRegion *pio_alias;
 MemoryRegion *mmio_alias;
 MemoryRegion *ecam_alias;
@@ -145,6 +147,29 @@ static const MemoryRegionOps loongson3_pm_ops = {
 }
 };
 
+static uint64_t loongson3_nodecnt_read(void *opaque,
+hwaddr addr, unsigned size)
+{
+LoongsonMachineState *s = opaque;
+int64_t now_ns = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
+uint64_t ticks = clock_ns_to_ticks(s->cpuclk, now_ns);
+
+if (addr == 0x4) {
+return ticks >> 32;
+}
+
+return ticks;
+}
+
+static const MemoryRegionOps loongson3_nodecnt_ops = {
+.read  = loongson3_nodecnt_read,
+.endianness = DEVICE_NATIVE_ENDIAN,
+.valid.min_access_size = 4,
+.valid.max_access_size = 8,
+.impl.min_access_size = 4,
+.impl.max_access_size = 8,
+};
+
 #define DEF_LOONGSON3_FREQ (800 * 1000 * 1000)
 
 static uint64_t get_cpu_freq_hz(void)
@@ -463,7 +488,6 @@ static void mips_loongson3_virt_init(MachineState *machine)
 int i;
 long bios_size;
 MIPSCPU *cpu;
-Clock *cpuclk;
 CPUMIPSState *env;
 DeviceState *liointc;
 char *filename;
@@ -471,10 +495,12 @@ static void mips_loongson3_virt_init(MachineState 
*machine)
 const char *kernel_filename = machine->kernel_filename;
 const char *initrd_filename = machine->initrd_filename;
 ram_addr_t ram_size = machine->ram_size;
+LoongsonMachineState *ms = LOONGSON_MACHINE(machine);
 MemoryRegion *address_space_mem = get_system_memory();
 MemoryRegion *ram = g_new(MemoryRegion, 1);
 MemoryRegion *bios = g_new(MemoryRegion, 1);
 MemoryRegion *iomem = g_new(MemoryRegion, 1);
+MemoryRegion *nodecnt = g_new(MemoryRegion, 1);
 
 /* TODO: TCG will support all CPU types */
 if (!kvm_enabled()) {
@@ -520,14 +546,14 @@ static void mips_loongson3_virt_init(MachineState 
*machine)
 sysbus_create_simple("goldfish_rtc", virt_memmap[VIRT_RTC].base,
  qdev_get_gpio_in(liointc, RTC_IRQ));
 
-cpuclk = clock_new(OBJECT(machine), "cpu-refclk");
-clock_set_hz(cpuclk, DEF_LOONGSON3_FREQ);
+ms->cpuclk = clock_new(OBJECT(machine), "cpu-refclk");
+clock_set_hz(ms->cpuclk, DEF_LOONGSON3_FREQ);
 
 for (i = 0; i < machine->smp.cpus; i++) {
 int ip;
 
 /* init CPUs */
-cpu = mips_cpu_create_with_clock(machine->cpu_type, cpuclk);
+cpu = mips_cpu_create_with_clock(machine->cpu_type, ms->cpuclk);
 
 /* Init internal devices */
 cpu_mips_irq_init_cpu(cpu);
@@ -553,6 +579,8 @@ static void mips_loongson3_virt_init(MachineState *machine)
machine->ram, 0, virt_memmap[VIRT_LOWMEM].size);
 memory_region_init_io(iomem, NULL, _pm_ops,
NULL, "loongson3_pm", virt_memmap[VIRT_PM].size);
+memory_region_init_io(nodecnt, NULL, _nodecnt_ops, ms,
+  "loongson3_nodecnt", virt_memmap[VIRT_NODECNT].size);
 
 memory_region_add_subregion(address_space_mem,
   virt_memmap[VIRT_LOWMEM].base, ram);
@@ -562,6 +590,8 @@ static void mips_loongson3_virt_init(MachineState *machine)
   virt_memmap[VIRT_HIGHMEM].base, machine->ram);
 memory_region_add_subregion(address_space_mem,
   virt_memmap[VIRT_PM].base, iomem);
+

Re: [PATCH 1/1] target/ppc: Move VMX integer add/sub saturate insns to decodetree.

2024-05-12 Thread Richard Henderson

On 5/12/24 11:38, Chinmay Rath wrote:

@@ -2934,6 +2870,184 @@ static bool do_vx_vaddsubcuw(DisasContext *ctx, arg_VX 
*a, int add)
  return true;
  }
  
+static inline void do_vadd_vsub_sat

+(
+unsigned vece, TCGv_vec t, TCGv_vec sat, TCGv_vec a, TCGv_vec b,
+void (*norm_op)(unsigned, TCGv_vec, TCGv_vec, TCGv_vec),
+void (*sat_op)(unsigned, TCGv_vec, TCGv_vec, TCGv_vec))
+{
+TCGv_vec x = tcg_temp_new_vec_matching(t);
+norm_op(vece, x, a, b);
+sat_op(vece, t, a, b);
+tcg_gen_cmp_vec(TCG_COND_NE, vece, x, x, t);
+tcg_gen_or_vec(vece, sat, sat, x);
+}


As a separate change, before or after, the cmp_vec may be simplified to xor_vec.  Which 
means that INDEX_op_cmp_vec need not be probed in the vecop_lists.  See


https://lore.kernel.org/qemu-devel/20240506010403.6204-31-richard.hender...@linaro.org/

which is performing the same operation on AArch64.



+static bool do_vx_vadd_vsub_sat(DisasContext *ctx, arg_VX *a,
+int sign, int vece, int add)
+{
+static const TCGOpcode vecop_list_sub_u[] = {
+INDEX_op_sub_vec, INDEX_op_ussub_vec, INDEX_op_cmp_vec, 0
+};
+static const TCGOpcode vecop_list_sub_s[] = {
+INDEX_op_sub_vec, INDEX_op_sssub_vec, INDEX_op_cmp_vec, 0
+};
+static const TCGOpcode vecop_list_add_u[] = {
+INDEX_op_add_vec, INDEX_op_usadd_vec, INDEX_op_cmp_vec, 0
+};
+static const TCGOpcode vecop_list_add_s[] = {
+INDEX_op_add_vec, INDEX_op_ssadd_vec, INDEX_op_cmp_vec, 0
+};
+
+static const GVecGen4 op[2][3][2] = {
+{
+{
+{
+.fniv = gen_vsub_sat_u,
+.fno = gen_helper_VSUBUBS,
+.opt_opc = vecop_list_sub_u,
+.write_aofs = true,
+.vece = MO_8
+},
+{
+.fniv = gen_vadd_sat_u,
+.fno = gen_helper_VADDUBS,
+.opt_opc = vecop_list_add_u,
+.write_aofs = true,
+.vece = MO_8
+},
+},
+{
+{
+.fniv = gen_vsub_sat_u,
+.fno = gen_helper_VSUBUHS,
+.opt_opc = vecop_list_sub_u,
+.write_aofs = true,
+.vece = MO_16
+},
+{
+.fniv = gen_vadd_sat_u,
+.fno = gen_helper_VADDUHS,
+.opt_opc = vecop_list_add_u,
+.write_aofs = true,
+.vece = MO_16
+},
+},
+{
+{
+.fniv = gen_vsub_sat_u,
+.fno = gen_helper_VSUBUWS,
+.opt_opc = vecop_list_sub_u,
+.write_aofs = true,
+.vece = MO_32
+},
+{
+.fniv = gen_vadd_sat_u,
+.fno = gen_helper_VADDUWS,
+.opt_opc = vecop_list_add_u,
+.write_aofs = true,
+.vece = MO_32
+},
+},
+},
+{
+{
+{
+.fniv = gen_vsub_sat_s,
+.fno = gen_helper_VSUBSBS,
+.opt_opc = vecop_list_sub_s,
+.write_aofs = true,
+.vece = MO_8
+},
+{
+.fniv = gen_vadd_sat_s,
+.fno = gen_helper_VADDSBS,
+.opt_opc = vecop_list_add_s,
+.write_aofs = true,
+.vece = MO_8
+},
+},
+{
+{
+.fniv = gen_vsub_sat_s,
+.fno = gen_helper_VSUBSHS,
+.opt_opc = vecop_list_sub_s,
+.write_aofs = true,
+.vece = MO_16
+},
+{
+.fniv = gen_vadd_sat_s,
+.fno = gen_helper_VADDSHS,
+.opt_opc = vecop_list_add_s,
+.write_aofs = true,
+.vece = MO_16
+},
+},
+{
+{
+.fniv = gen_vsub_sat_s,
+.fno = gen_helper_VSUBSWS,
+.opt_opc = vecop_list_sub_s,
+.write_aofs = true,
+.vece = MO_32
+},
+{
+.fniv = gen_vadd_sat_s,
+.fno = gen_helper_VADDSWS,
+.opt_opc = vecop_list_add_s,
+.write_aofs = true,
+.vece = MO_32
+},
+},
+},
+};


While this table is not wrong, I think it is clearer to have separate tables, one per 

[PATCH v2 2/2] ui/gtk: Fix mouse/motion event scaling issue with GTK display backend

2024-05-12 Thread hikalium
Remove gtk_widget_get_scale_factor() usage from the calculation of
the motion events in the GTK backend to make it work correctly on
environments that have `gtk_widget_get_scale_factor() != 1`.

This scale factor usage had been introduced in the commit f14aab420c and
at that time the window size was used for calculating the things and it
was working correctly. However, in the commit 2f31663ed4 the logic
switched to use the widget size instead of window size and because of
the change the usage of scale factor becomes invalid (since widgets use
`vc->gfx.scale_{x, y}` for scaling).

Tested on Crostini on ChromeOS (15823.51.0) with an external display.

Fixes: 2f31663ed4 ("ui/gtk: use widget size for cursor motion event")
Fixes: f14aab420c ("ui: fix incorrect pointer position on highdpi with
gtk")

Signed-off-by: hikalium 
---
 ui/gtk.c | 18 +-
 1 file changed, 13 insertions(+), 5 deletions(-)

diff --git a/ui/gtk.c b/ui/gtk.c
index ebae888d4f..4386198c95 100644
--- a/ui/gtk.c
+++ b/ui/gtk.c
@@ -887,7 +887,7 @@ static gboolean gd_motion_event(GtkWidget *widget, 
GdkEventMotion *motion,
 int x, y;
 int mx, my;
 int fbh, fbw;
-int ww, wh, ws;
+int ww, wh;
 
 if (!vc->gfx.ds) {
 return TRUE;
@@ -895,11 +895,15 @@ static gboolean gd_motion_event(GtkWidget *widget, 
GdkEventMotion *motion,
 
 fbw = surface_width(vc->gfx.ds) * vc->gfx.scale_x;
 fbh = surface_height(vc->gfx.ds) * vc->gfx.scale_y;
-
 ww = gtk_widget_get_allocated_width(widget);
 wh = gtk_widget_get_allocated_height(widget);
-ws = gtk_widget_get_scale_factor(widget);
 
+/*
+ * `widget` may not have the same size with the frame buffer.
+ * In such cases, some paddings are needed around the `vc`.
+ * To achieve that, `vc` will be displayed at (mx, my)
+ * so that it is displayed at the center of the widget.
+ */
 mx = my = 0;
 if (ww > fbw) {
 mx = (ww - fbw) / 2;
@@ -908,8 +912,12 @@ static gboolean gd_motion_event(GtkWidget *widget, 
GdkEventMotion *motion,
 my = (wh - fbh) / 2;
 }
 
-x = (motion->x - mx) / vc->gfx.scale_x * ws;
-y = (motion->y - my) / vc->gfx.scale_y * ws;
+/*
+ * `motion` is reported in `widget` coordinates
+ * so translating it to the coordinates in `vc`.
+ */
+x = (motion->x - mx) / vc->gfx.scale_x;
+y = (motion->y - my) / vc->gfx.scale_y;
 
 trace_gd_motion_event(ww, wh, gtk_widget_get_scale_factor(widget), x, y);
 
-- 
2.39.2




[PATCH v2 1/2] ui/gtk: Add gd_motion_event trace event

2024-05-12 Thread hikalium
Add gd_motion_event trace event for making it easy to debug
gd_motion_event related issues.

Signed-off-by: hikalium 
---
 ui/gtk.c| 2 ++
 ui/trace-events | 1 +
 2 files changed, 3 insertions(+)

diff --git a/ui/gtk.c b/ui/gtk.c
index 810d7fc796..ebae888d4f 100644
--- a/ui/gtk.c
+++ b/ui/gtk.c
@@ -911,6 +911,8 @@ static gboolean gd_motion_event(GtkWidget *widget, 
GdkEventMotion *motion,
 x = (motion->x - mx) / vc->gfx.scale_x * ws;
 y = (motion->y - my) / vc->gfx.scale_y * ws;
 
+trace_gd_motion_event(ww, wh, gtk_widget_get_scale_factor(widget), x, y);
+
 if (qemu_input_is_absolute(vc->gfx.dcl.con)) {
 if (x < 0 || y < 0 ||
 x >= surface_width(vc->gfx.ds) ||
diff --git a/ui/trace-events b/ui/trace-events
index e6a2894303..69ff22955d 100644
--- a/ui/trace-events
+++ b/ui/trace-events
@@ -28,6 +28,7 @@ gd_ungrab(const char *tab, const char *device) "tab=%s, 
dev=%s"
 gd_keymap_windowing(const char *name) "backend=%s"
 gd_gl_area_create_context(void *ctx, int major, int minor) "ctx=%p, major=%d, 
minor=%d"
 gd_gl_area_destroy_context(void *ctx, void *current_ctx) "ctx=%p, 
current_ctx=%p"
+gd_motion_event(int ww, int wh, int ws, int x, int y) "ww=%d, wh=%d, ws=%d, 
x=%d, y=%d"
 
 # vnc-auth-sasl.c
 # vnc-auth-vencrypt.c
-- 
2.39.2




[PATCH v2 0/2] ui/gtk: Fix motion event scaling issue

2024-05-12 Thread hikalium
Hi there,

This is a v2 of the previous series with nit fixes (fixing typo,
adding component prefix for each patch subjects, and adding a cover
letter).

Please take a look. Thank you!

hikalium (2):
  ui/gtk: Add gd_motion_event trace event
  ui/gtk: Fix mouse/motion event scaling issue with GTK display backend

 ui/gtk.c| 20 +++-
 ui/trace-events |  1 +
 2 files changed, 16 insertions(+), 5 deletions(-)

-- 
2.39.2




[PULL 01/27] target/i386: remove PCOMMIT from TCG, deprecate property

2024-05-12 Thread Paolo Bonzini
The PCOMMIT instruction was never included in any physical processor.
TCG implements it as a no-op instruction, but its utility is debatable
to say the least.  Drop it from the decoder since it is only available
with "-cpu max", which does not guarantee migration compatibility
across versions, and deprecate the property just in case someone is
using it as "pcommit=off".

Reviewed-by: Richard Henderson 
Signed-off-by: Paolo Bonzini 
---
 docs/about/deprecated.rst   |  8 
 target/i386/cpu.h   |  2 --
 target/i386/cpu.c   |  2 +-
 target/i386/tcg/translate.c | 12 +---
 4 files changed, 10 insertions(+), 14 deletions(-)

diff --git a/docs/about/deprecated.rst b/docs/about/deprecated.rst
index 5c3ca47801f..40585ca7d55 100644
--- a/docs/about/deprecated.rst
+++ b/docs/about/deprecated.rst
@@ -432,6 +432,14 @@ Backend ``memory`` (since 9.0)
 CPU device properties
 '
 
+``pcommit`` on x86 (since 9.1)
+^^
+
+The PCOMMIT instruction was never included in any physical processor.
+It was implemented as a no-op instruction in TCG up to QEMU 9.0, but
+only with ``-cpu max`` (which does not guarantee migration compatibility
+across versions).
+
 ``pmu-num=n`` on RISC-V CPUs (since 8.2)
 
 
diff --git a/target/i386/cpu.h b/target/i386/cpu.h
index 1e0d2c915f5..b62fc35 100644
--- a/target/i386/cpu.h
+++ b/target/i386/cpu.h
@@ -816,8 +816,6 @@ uint64_t x86_cpu_get_supported_feature_word(FeatureWord w,
 #define CPUID_7_0_EBX_SMAP  (1U << 20)
 /* AVX-512 Integer Fused Multiply Add */
 #define CPUID_7_0_EBX_AVX512IFMA(1U << 21)
-/* Persistent Commit */
-#define CPUID_7_0_EBX_PCOMMIT   (1U << 22)
 /* Flush a Cache Line Optimized */
 #define CPUID_7_0_EBX_CLFLUSHOPT(1U << 23)
 /* Cache Line Write Back */
diff --git a/target/i386/cpu.c b/target/i386/cpu.c
index 1058b6803fd..79372de8c5a 100644
--- a/target/i386/cpu.c
+++ b/target/i386/cpu.c
@@ -713,7 +713,7 @@ void x86_cpu_vendor_words2str(char *dst, uint32_t vendor1,
 #endif
 #define TCG_7_0_EBX_FEATURES (CPUID_7_0_EBX_SMEP | CPUID_7_0_EBX_SMAP | \
   CPUID_7_0_EBX_BMI1 | CPUID_7_0_EBX_BMI2 | CPUID_7_0_EBX_ADX | \
-  CPUID_7_0_EBX_PCOMMIT | CPUID_7_0_EBX_CLFLUSHOPT |\
+  CPUID_7_0_EBX_CLFLUSHOPT |\
   CPUID_7_0_EBX_CLWB | CPUID_7_0_EBX_MPX | CPUID_7_0_EBX_FSGSBASE | \
   CPUID_7_0_EBX_ERMS | CPUID_7_0_EBX_AVX2 | CPUID_7_0_EBX_RDSEED | \
   CPUID_7_0_EBX_SHA_NI | CPUID_7_0_EBX_KERNEL_FEATURES)
diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c
index 3842b294842..7d9f6b5c55b 100644
--- a/target/i386/tcg/translate.c
+++ b/target/i386/tcg/translate.c
@@ -4487,17 +4487,7 @@ static void disas_insn_old(DisasContext *s, CPUState 
*cpu, int b)
 }
 goto unknown_op;
 
-case 0xf8: /* sfence / pcommit */
-if (prefixes & PREFIX_DATA) {
-/* pcommit */
-if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_PCOMMIT)
-|| (prefixes & PREFIX_LOCK)) {
-goto illegal_op;
-}
-break;
-}
-/* fallthru */
-case 0xf9 ... 0xff: /* sfence */
+case 0xf8 ... 0xff: /* sfence */
 if (!(s->cpuid_features & CPUID_SSE)
 || (prefixes & PREFIX_LOCK)) {
 goto illegal_op;
-- 
2.45.0




[PULL 06/27] tests/tcg: cover lzcnt/tzcnt/popcnt

2024-05-12 Thread Paolo Bonzini
Reviewed-by: Zhao Liu 
Signed-off-by: Paolo Bonzini 
---
 tests/tcg/i386/test-i386.c | 25 +
 1 file changed, 25 insertions(+)

diff --git a/tests/tcg/i386/test-i386.c b/tests/tcg/i386/test-i386.c
index 864c4e620d5..ce3bf74b5a8 100644
--- a/tests/tcg/i386/test-i386.c
+++ b/tests/tcg/i386/test-i386.c
@@ -715,6 +715,30 @@ void test_mul(void)
 printf("%-10s A=" FMTLX " R=" FMTLX " %ld\n", #op, val, res, resz);\
 }
 
+void test_xcnt(void)
+{
+TEST_BSX(tzcntw, "w", 0);
+TEST_BSX(tzcntw, "w", 0x12340128);
+TEST_BSX(lzcntw, "w", 0);
+TEST_BSX(lzcntw, "w", 0x12340128);
+TEST_BSX(popcntw, "w", 0);
+TEST_BSX(popcntw, "w", 0x12340128);
+TEST_BSX(tzcntl, "k", 0);
+TEST_BSX(tzcntl, "k", 0x00340128);
+TEST_BSX(lzcntl, "k", 0);
+TEST_BSX(lzcntl, "k", 0x00340128);
+TEST_BSX(popcntl, "k", 0);
+TEST_BSX(popcntl, "k", 0x00340128);
+#if defined(__x86_64__)
+TEST_BSX(tzcntq, "", 0);
+TEST_BSX(tzcntq, "", 0x003401281234);
+TEST_BSX(lzcntq, "", 0);
+TEST_BSX(lzcntq, "", 0x003401281234);
+TEST_BSX(popcntq, "", 0);
+TEST_BSX(popcntq, "", 0x003401281234);
+#endif
+}
+
 void test_bsx(void)
 {
 TEST_BSX(bsrw, "w", 0);
@@ -2162,6 +2186,7 @@ int main(int argc, char **argv)
 func();
 }
 test_bsx();
+test_xcnt();
 test_mul();
 test_jcc();
 test_loop();
-- 
2.45.0




[PULL 00/27] Build/arch cleanups, target/i386 fixes for 2024-05-10

2024-05-12 Thread Paolo Bonzini
The following changes since commit dafec285bdbfe415ac6823abdc510e0b92c3f094:

  Merge tag 'pull-request-2024-05-10' of https://gitlab.com/thuth/qemu into 
staging (2024-05-10 09:41:35 +0200)

are available in the Git repository at:

  https://gitlab.com/bonzini/qemu.git tags/for-upstream

for you to fetch changes up to 9b089d254a5623baef01f7d0ec37331c1155f1ce:

  configs: disable emulators that require it if libfdt is not found (2024-05-10 
15:45:15 +0200)


* target/i386: miscellaneous changes, mostly TCG-related
* fix --without-default-devices build
* fix --without-default-devices qtests on s390x and arm


Paolo Bonzini (27):
  target/i386: remove PCOMMIT from TCG, deprecate property
  target/i386: fix operand size for DATA16 REX.W POPCNT
  target/i386: rdpkru/wrpkru are no-prefix instructions
  target/i386: move prefetch and multi-byte UD/NOP to new decoder
  target/i386: fix feature dependency for WAITPKG
  tests/tcg: cover lzcnt/tzcnt/popcnt
  configure: quote -D options that are passed through to meson
  sh4: select correct components for no-board build
  s390x: move s390_cpu_addr2state to target/s390x/sigp.c
  s390_flic: add migration-enabled property
  s390: move css_migration_enabled from machine to css.c
  s390x: select correct components for no-board build
  tests/qtest: s390x: fix operation in a build without any boards or devices
  xen: initialize legacy backends from xen_bus_init()
  xen: register legacy backends via xen_backend_init
  i386: correctly select code in hw/i386 that depends on other components
  i386: pc: remove unnecessary MachineClass overrides
  hw/i386: split x86.c in multiple parts
  hw/i386: move rtc-reset-reinjection command out of hw/rtc
  i386: select correct components for no-board build
  tests/qtest: arm: fix operation in a build without any boards or devices
  meson: pick libfdt from common_ss when building target-specific files
  meson: move libfdt together with other dependencies
  kconfig: allow compiling out QEMU device tree code per target
  kconfig: express dependency of individual boards on libfdt
  hw/xtensa: require libfdt
  configs: disable emulators that require it if libfdt is not found

 docs/about/deprecated.rst|8 +
 configure|2 +-
 configs/targets/aarch64-softmmu.mak  |1 +
 configs/targets/arm-softmmu.mak  |1 +
 configs/targets/i386-softmmu.mak |1 -
 configs/targets/loongarch64-softmmu.mak  |1 +
 configs/targets/microblaze-softmmu.mak   |1 +
 configs/targets/microblazeel-softmmu.mak |1 +
 configs/targets/mips64el-softmmu.mak |1 -
 configs/targets/or1k-softmmu.mak |1 +
 configs/targets/ppc-softmmu.mak  |1 -
 configs/targets/ppc64-softmmu.mak|1 +
 configs/targets/riscv32-softmmu.mak  |1 +
 configs/targets/riscv64-softmmu.mak  |1 +
 configs/targets/rx-softmmu.mak   |1 +
 configs/targets/x86_64-softmmu.mak   |1 -
 meson.build  |  100 +--
 include/hw/i386/x86.h|   10 +-
 include/hw/rtc/mc146818rtc.h |2 +-
 include/hw/s390x/css.h   |6 +
 include/hw/s390x/s390-virtio-ccw.h   |7 -
 include/hw/s390x/s390_flic.h |1 +
 include/hw/xen/xen-legacy-backend.h  |   14 +-
 include/hw/xen/xen_pvdev.h   |1 -
 include/monitor/hmp.h|1 +
 include/sysemu/device_tree.h |1 -
 target/i386/cpu.h|2 -
 target/i386/tcg/decode-new.h |1 +
 hw/9pfs/xen-9p-backend.c |8 +-
 hw/display/xenfb.c   |8 +-
 hw/i386/fw_cfg.c |2 +
 hw/i386/monitor.c|   46 ++
 hw/i386/pc.c |4 -
 hw/i386/x86-common.c | 1007 
 hw/i386/x86-cpu.c|   97 +++
 hw/i386/x86.c| 1058 +-
 hw/intc/ioapic-stub.c|   29 +
 hw/intc/s390_flic.c  |6 +-
 hw/rtc/mc146818rtc.c |   12 +-
 hw/s390x/css.c   |   10 +-
 hw/s390x/s390-virtio-ccw.c   |   32 +-
 hw/usb/xen-usb.c |   14 +-
 hw/xen/xen-bus.c |4 +
 hw/xen/xen-hvm-common.c  |2 -
 hw/xen/xen-legacy-backend.c  |   16 -
 hw/xenpv/xen_machine_pv.c|5 +-
 hw/xtensa/xtfpga.c   |9 -
 monitor/hmp-cmds.c   |   17 +
 system/device_tree-stub.c|   10 +
 

[PULL 27/27] configs: disable emulators that require it if libfdt is not found

2024-05-12 Thread Paolo Bonzini
Since boards can express their dependency on libfdt and
system/device_tree.c, only leave TARGET_NEED_FDT if the target has a
hard dependency.

Those emulators will be skipped if libfdt is disabled, or if it
is "auto" and not found and --disable-download is passed; unless
the target is mentioned explicitly in --target-list, in which case
the build will fail.

Reviewed-by: Philippe Mathieu-Daudé 
Signed-off-by: Paolo Bonzini 
---
 configs/targets/aarch64-softmmu.mak  | 1 +
 configs/targets/arm-softmmu.mak  | 1 +
 configs/targets/i386-softmmu.mak | 1 -
 configs/targets/loongarch64-softmmu.mak  | 1 +
 configs/targets/microblaze-softmmu.mak   | 1 +
 configs/targets/microblazeel-softmmu.mak | 1 +
 configs/targets/mips64el-softmmu.mak | 1 -
 configs/targets/or1k-softmmu.mak | 1 +
 configs/targets/ppc-softmmu.mak  | 1 -
 configs/targets/ppc64-softmmu.mak| 1 +
 configs/targets/riscv32-softmmu.mak  | 1 +
 configs/targets/riscv64-softmmu.mak  | 1 +
 configs/targets/rx-softmmu.mak   | 1 +
 configs/targets/x86_64-softmmu.mak   | 1 -
 meson.build  | 6 +-
 .gitlab-ci.d/buildtest.yml   | 8 
 16 files changed, 19 insertions(+), 9 deletions(-)

diff --git a/configs/targets/aarch64-softmmu.mak 
b/configs/targets/aarch64-softmmu.mak
index 83c22391a69..84cb32dc2f4 100644
--- a/configs/targets/aarch64-softmmu.mak
+++ b/configs/targets/aarch64-softmmu.mak
@@ -3,4 +3,5 @@ TARGET_BASE_ARCH=arm
 TARGET_SUPPORTS_MTTCG=y
 TARGET_KVM_HAVE_GUEST_DEBUG=y
 TARGET_XML_FILES= gdb-xml/aarch64-core.xml gdb-xml/aarch64-fpu.xml 
gdb-xml/arm-core.xml gdb-xml/arm-vfp.xml gdb-xml/arm-vfp3.xml 
gdb-xml/arm-vfp-sysregs.xml gdb-xml/arm-neon.xml gdb-xml/arm-m-profile.xml 
gdb-xml/arm-m-profile-mve.xml gdb-xml/aarch64-pauth.xml
+# needed by boot.c
 TARGET_NEED_FDT=y
diff --git a/configs/targets/arm-softmmu.mak b/configs/targets/arm-softmmu.mak
index 92c8349b964..bf390b7a8de 100644
--- a/configs/targets/arm-softmmu.mak
+++ b/configs/targets/arm-softmmu.mak
@@ -1,4 +1,5 @@
 TARGET_ARCH=arm
 TARGET_SUPPORTS_MTTCG=y
 TARGET_XML_FILES= gdb-xml/arm-core.xml gdb-xml/arm-vfp.xml 
gdb-xml/arm-vfp3.xml gdb-xml/arm-vfp-sysregs.xml gdb-xml/arm-neon.xml 
gdb-xml/arm-m-profile.xml gdb-xml/arm-m-profile-mve.xml
+# needed by boot.c
 TARGET_NEED_FDT=y
diff --git a/configs/targets/i386-softmmu.mak b/configs/targets/i386-softmmu.mak
index d61b5076134..2ac69d5ba37 100644
--- a/configs/targets/i386-softmmu.mak
+++ b/configs/targets/i386-softmmu.mak
@@ -1,5 +1,4 @@
 TARGET_ARCH=i386
 TARGET_SUPPORTS_MTTCG=y
-TARGET_NEED_FDT=y
 TARGET_KVM_HAVE_GUEST_DEBUG=y
 TARGET_XML_FILES= gdb-xml/i386-32bit.xml
diff --git a/configs/targets/loongarch64-softmmu.mak 
b/configs/targets/loongarch64-softmmu.mak
index f23780fdd89..84beb19b90a 100644
--- a/configs/targets/loongarch64-softmmu.mak
+++ b/configs/targets/loongarch64-softmmu.mak
@@ -2,4 +2,5 @@ TARGET_ARCH=loongarch64
 TARGET_BASE_ARCH=loongarch
 TARGET_SUPPORTS_MTTCG=y
 TARGET_XML_FILES= gdb-xml/loongarch-base32.xml gdb-xml/loongarch-base64.xml 
gdb-xml/loongarch-fpu.xml
+# all boards require libfdt
 TARGET_NEED_FDT=y
diff --git a/configs/targets/microblaze-softmmu.mak 
b/configs/targets/microblaze-softmmu.mak
index e84c0cc7283..eea266d4f3d 100644
--- a/configs/targets/microblaze-softmmu.mak
+++ b/configs/targets/microblaze-softmmu.mak
@@ -1,5 +1,6 @@
 TARGET_ARCH=microblaze
 TARGET_BIG_ENDIAN=y
 TARGET_SUPPORTS_MTTCG=y
+# needed by boot.c
 TARGET_NEED_FDT=y
 TARGET_XML_FILES=gdb-xml/microblaze-core.xml 
gdb-xml/microblaze-stack-protect.xml
diff --git a/configs/targets/microblazeel-softmmu.mak 
b/configs/targets/microblazeel-softmmu.mak
index 9b688036bd3..77b968acad3 100644
--- a/configs/targets/microblazeel-softmmu.mak
+++ b/configs/targets/microblazeel-softmmu.mak
@@ -1,4 +1,5 @@
 TARGET_ARCH=microblaze
 TARGET_SUPPORTS_MTTCG=y
+# needed by boot.c
 TARGET_NEED_FDT=y
 TARGET_XML_FILES=gdb-xml/microblaze-core.xml 
gdb-xml/microblaze-stack-protect.xml
diff --git a/configs/targets/mips64el-softmmu.mak 
b/configs/targets/mips64el-softmmu.mak
index 8d9ab3ddc4b..3864daa7364 100644
--- a/configs/targets/mips64el-softmmu.mak
+++ b/configs/targets/mips64el-softmmu.mak
@@ -1,3 +1,2 @@
 TARGET_ARCH=mips64
 TARGET_BASE_ARCH=mips
-TARGET_NEED_FDT=y
diff --git a/configs/targets/or1k-softmmu.mak b/configs/targets/or1k-softmmu.mak
index 432f855a30a..0341cb2a6b3 100644
--- a/configs/targets/or1k-softmmu.mak
+++ b/configs/targets/or1k-softmmu.mak
@@ -1,4 +1,5 @@
 TARGET_ARCH=openrisc
 TARGET_SUPPORTS_MTTCG=y
 TARGET_BIG_ENDIAN=y
+# needed by boot.c and all boards
 TARGET_NEED_FDT=y
diff --git a/configs/targets/ppc-softmmu.mak b/configs/targets/ppc-softmmu.mak
index f3ea9c98f75..53120dab41d 100644
--- a/configs/targets/ppc-softmmu.mak
+++ b/configs/targets/ppc-softmmu.mak
@@ -2,4 +2,3 @@ TARGET_ARCH=ppc
 TARGET_BIG_ENDIAN=y
 TARGET_KVM_HAVE_GUEST_DEBUG=y
 TARGET_XML_FILES= gdb-xml/power-core.xml gdb-xml/power-fpu.xml 

[PULL 26/27] hw/xtensa: require libfdt

2024-05-12 Thread Paolo Bonzini
All other boards require libfdt if it can be used (including for example
i386/x86_64), so change the "imply" to "select" and always allow -dtb
in qemu-system-xtensa.

Reviewed-by: Philippe Mathieu-Daudé 
Signed-off-by: Paolo Bonzini 
---
 hw/xtensa/xtfpga.c | 9 -
 hw/xtensa/Kconfig  | 4 ++--
 2 files changed, 2 insertions(+), 11 deletions(-)

diff --git a/hw/xtensa/xtfpga.c b/hw/xtensa/xtfpga.c
index f49e6591dc2..955e8867a36 100644
--- a/hw/xtensa/xtfpga.c
+++ b/hw/xtensa/xtfpga.c
@@ -356,7 +356,6 @@ static void xtfpga_init(const XtfpgaBoardDesc *board, 
MachineState *machine)
 cur_tagptr = put_tag(cur_tagptr, BP_TAG_COMMAND_LINE,
  strlen(kernel_cmdline) + 1, kernel_cmdline);
 }
-#ifdef CONFIG_FDT
 if (dtb_filename) {
 int fdt_size;
 void *fdt = load_device_tree(dtb_filename, _size);
@@ -373,14 +372,6 @@ static void xtfpga_init(const XtfpgaBoardDesc *board, 
MachineState *machine)
 cur_lowmem = QEMU_ALIGN_UP(cur_lowmem + fdt_size, 4 * KiB);
 g_free(fdt);
 }
-#else
-if (dtb_filename) {
-error_report("could not load DTB '%s': "
- "FDT support is not configured in QEMU",
- dtb_filename);
-exit(EXIT_FAILURE);
-}
-#endif
 if (initrd_filename) {
 BpMemInfo initrd_location = { 0 };
 int initrd_size = load_ramdisk(initrd_filename, cur_lowmem,
diff --git a/hw/xtensa/Kconfig b/hw/xtensa/Kconfig
index 8ea283a7a3b..fc5c785cfac 100644
--- a/hw/xtensa/Kconfig
+++ b/hw/xtensa/Kconfig
@@ -14,8 +14,8 @@ config XTENSA_VIRT
 config XTENSA_XTFPGA
 bool
 default y
-depends on XTENSA
-imply DEVICE_TREE
+depends on XTENSA && FDT
+select DEVICE_TREE
 select OPENCORES_ETH
 select PFLASH_CFI01
 select SERIAL
-- 
2.45.0




[PULL 03/27] target/i386: rdpkru/wrpkru are no-prefix instructions

2024-05-12 Thread Paolo Bonzini
Reject 0x66/0xf3/0xf2 in front of them.

Cc: qemu-sta...@nongnu.org
Reviewed-by: Richard Henderson 
Signed-off-by: Paolo Bonzini 
---
 target/i386/tcg/translate.c | 6 --
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c
index 5366dc32dd3..3da4fdf64cc 100644
--- a/target/i386/tcg/translate.c
+++ b/target/i386/tcg/translate.c
@@ -3907,7 +3907,8 @@ static void disas_insn_old(DisasContext *s, CPUState 
*cpu, int b)
 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 1);
 break;
 case 0xee: /* rdpkru */
-if (prefixes & PREFIX_LOCK) {
+if (s->prefix & (PREFIX_LOCK | PREFIX_DATA
+ | PREFIX_REPZ | PREFIX_REPNZ)) {
 goto illegal_op;
 }
 tcg_gen_trunc_tl_i32(s->tmp2_i32, cpu_regs[R_ECX]);
@@ -3915,7 +3916,8 @@ static void disas_insn_old(DisasContext *s, CPUState 
*cpu, int b)
 tcg_gen_extr_i64_tl(cpu_regs[R_EAX], cpu_regs[R_EDX], s->tmp1_i64);
 break;
 case 0xef: /* wrpkru */
-if (prefixes & PREFIX_LOCK) {
+if (s->prefix & (PREFIX_LOCK | PREFIX_DATA
+ | PREFIX_REPZ | PREFIX_REPNZ)) {
 goto illegal_op;
 }
 tcg_gen_concat_tl_i64(s->tmp1_i64, cpu_regs[R_EAX],
-- 
2.45.0




  1   2   >