Re: How unsubscribe

2024-05-07 Thread Thomas Huth

On 08/05/2024 00.20, Jean-Christophe wrote:

Hello,
How unsubscribe ?


Go to https://lists.nongnu.org/mailman/listinfo/qemu-devel and look at the 
bottom.


 HTH,
  Thomas





[PATCH] scripts/simpletrace: Mark output with unstable timestamp as WARN

2024-05-07 Thread Zhao Liu
In some trace log, there're unstable timestamp breaking temporal
ordering of trace records. For example:

kvm_run_exit -0.015 pid=3289596 cpu_index=0x0 reason=0x6
kvm_vm_ioctl -0.020 pid=3289596 type=0xc008ae67 arg=0x7ffeefb5aa60
kvm_vm_ioctl -0.021 pid=3289596 type=0xc008ae67 arg=0x7ffeefb5aa60

Negative delta intervals tend to get drowned in the massive trace logs,
and an unstable timestamp can corrupt the calculation of intervals
between two events adjacent to it.

Therefore, mark the outputs with unstable timestamps as WARN like:

WARN: skip unstable timestamp: kvm_run_exit 
cur(8497404907761146)-pre(8497404907761161) pid=3289596 cpu_index=0x0 reason=0x6
WARN: skip unstable timestamp: kvm_vm_ioctl 
cur(8497404908603653)-pre(8497404908603673) pid=3289596 type=0xc008ae67 
arg=0x7ffeefb5aa60
WARN: skip unstable timestamp: kvm_vm_ioctl 
cur(8497404908625787)-pre(8497404908625808) pid=3289596 type=0xc008ae67 
arg=0x7ffeefb5aa60

This would help to identify unusual events.

And skip them without updating Formatter2.last_timestamp_ns to avoid
time back.

Signed-off-by: Zhao Liu 
---
 scripts/simpletrace.py | 11 +++
 1 file changed, 11 insertions(+)

diff --git a/scripts/simpletrace.py b/scripts/simpletrace.py
index cef81b0707f0..23911dddb8a6 100755
--- a/scripts/simpletrace.py
+++ b/scripts/simpletrace.py
@@ -343,6 +343,17 @@ def __init__(self):
 def catchall(self, *rec_args, event, timestamp_ns, pid, event_id):
 if self.last_timestamp_ns is None:
 self.last_timestamp_ns = timestamp_ns
+
+if timestamp_ns < self.last_timestamp_ns:
+fields = [
+f'{name}={r}' if is_string(type) else f'{name}=0x{r:x}'
+for r, (type, name) in zip(rec_args, event.args)
+]
+print(f'WARN: skip unstable timestamp: {event.name} '
+  f'cur({timestamp_ns})-pre({self.last_timestamp_ns}) 
{pid=} ' +
+  f' '.join(fields))
+return
+
 delta_ns = timestamp_ns - self.last_timestamp_ns
 self.last_timestamp_ns = timestamp_ns
 
-- 
2.34.1




Re: [PATCH] hw/virtio: Fix obtain the buffer id from the last descriptor

2024-05-07 Thread Jason Wang
On Mon, Apr 22, 2024 at 9:41 AM Wafer  wrote:
>
> The virtio-1.3 specification
>  writes:
> 2.8.6 Next Flag: Descriptor Chaining
>   Buffer ID is included in the last descriptor in the list.
>
> If the feature (_F_INDIRECT_DESC) has been negotiated, install only
> one descriptor in the virtqueue.
> Therefor the buffer id should be obtained from the first descriptor.
>
> In descriptor chaining scenarios, the buffer id should be obtained
> from the last descriptor.
>
> Fixes: 86044b24e8 ("virtio: basic packed virtqueue support")
>
> Signed-off-by: Wafer 
> ---
>  hw/virtio/virtio.c | 5 +
>  1 file changed, 5 insertions(+)
>
> diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c
> index 871674f9be..f65d4b4161 100644
> --- a/hw/virtio/virtio.c
> +++ b/hw/virtio/virtio.c
> @@ -1739,6 +1739,11 @@ static void *virtqueue_packed_pop(VirtQueue *vq, 
> size_t sz)
>  goto err_undo_map;
>  }
>
> +if (desc_cache != _desc_cache) {
> +/* Buffer ID is included in the last descriptor in the list. */
> +id = desc.id;
> +}

It looks to me we can move this out of the loop.

Others look good.

Thanks

> +
>  rc = virtqueue_packed_read_next_desc(vq, , desc_cache, max, ,
>   desc_cache ==
>   _desc_cache);
> --
> 2.27.0
>




Re: Intention to work on GSoC project

2024-05-07 Thread Sahil
Hi,

On Tuesday, May 7, 2024 12:44:33 PM IST Eugenio Perez Martin wrote:
> [...]
> > Shall I start by implementing a mechanism to check if the feature bit
> > "VIRTIO_F_RING_PACKED" is set (using "virtio_vdev_has_feature")? And
> > if it's supported, "vhost_svq_add" should call "vhost_svq_add_packed".
> > Following this, I can then start implementing "vhost_svq_add_packed"
> > and progress from there.
> > 
> > What are your thoughts on this?
> 
> Yes, that's totally right.
> 
> I recommend you to also disable _F_EVENT_IDX to start, so the first
> version is easier.
> 
> Also, you can send as many incomplete RFCs as you want. For example,
> you can send a first version that only implements reading of the guest
> avail ring, so we know we're aligned on that. Then, we can send
> subsequents RFCs adding features on top.
> 
> Does that make sense to you?
> 
> Thanks!
>

Thank you for your reply. This is perfect. I'll start with this and will
send the first RFC as soon as possible.

Thanks,
Sahil







[PATCH v4 0/5] Add migration test for loongarch64

2024-05-07 Thread Bibo Mao
Migration test case is added for loongarch64 here. Since compat machine
type is required for migration test case, also compat machine qemu 9.0
is added for loongarch virt machine.

Migration test case passes to run in both tcg and kvm mode with the
patch, 54 migration subtests passes in 188 seconds.

---
v3 ... v4:
  1. Rename VIRT_MACHINE with LOONGARCH_VIRT_MACHINE since other
architectures have the same machine type.

v2 ... v3:
  1. Refresh the patch based on the latest qemu version, solve the
confliction issue.

v1 ... v2:
  1. Keep the default memory size unchanged with 1GB, only modify minimum
memory size with 256MB
  2. Remove tab char in file tests/migration/loongarch64/a-b-kernel.S
---
Bibo Mao (5):
  hw/loongarch: Rename LOONGARCH_MACHINE with LOONGARCH_VIRT_MACHINE
  hw/loongarch: Rename LoongArchMachineState with
LoongArchVirtMachineState
  hw/loongarch: Add compat machine for 9.0
  hw/loongarch: Set minimium memory size as 256M
  tests: Add migration test for loongarch64

 hw/loongarch/acpi-build.c|  88 ++---
 hw/loongarch/boot.c  |  10 +-
 hw/loongarch/fw_cfg.c|   2 +-
 hw/loongarch/fw_cfg.h|   2 +-
 hw/loongarch/virt.c  | 393 ---
 include/hw/loongarch/virt.h  |   9 +-
 tests/migration/Makefile |   2 +-
 tests/migration/loongarch64/Makefile |  18 ++
 tests/migration/loongarch64/a-b-kernel.S |  49 +++
 tests/migration/loongarch64/a-b-kernel.h |  16 +
 tests/migration/migration-test.h |   3 +
 tests/qtest/meson.build  |   4 +
 tests/qtest/migration-test.c |  10 +
 13 files changed, 370 insertions(+), 236 deletions(-)
 create mode 100644 tests/migration/loongarch64/Makefile
 create mode 100644 tests/migration/loongarch64/a-b-kernel.S
 create mode 100644 tests/migration/loongarch64/a-b-kernel.h


base-commit: 4e66a08546a2588a4667766a1edab9caccf24ce3
-- 
2.39.3




[PATCH v4 4/5] hw/loongarch: Set minimium memory size as 256M

2024-05-07 Thread Bibo Mao
The minimum memory size for LoongArch UEFI bios is 256M, also some
test cases such as migration and qos use 256M memory by default.

Here set minimum memory size for Loongarch VirtMachine with 256M rather
than 1G, so that test cases with 256M memory can pass to run.

Signed-off-by: Bibo Mao 
---
 hw/loongarch/virt.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c
index c3bb343574..5d590cf92f 100644
--- a/hw/loongarch/virt.c
+++ b/hw/loongarch/virt.c
@@ -894,8 +894,8 @@ static void virt_init(MachineState *machine)
 cpu_model = LOONGARCH_CPU_TYPE_NAME("la464");
 }
 
-if (ram_size < 1 * GiB) {
-error_report("ram_size must be greater than 1G.");
+if (ram_size < 256 * MiB) {
+error_report("ram_size must be greater than 256M.");
 exit(1);
 }
 create_fdt(lvms);
-- 
2.39.3




[PATCH v4 1/5] hw/loongarch: Rename LOONGARCH_MACHINE with LOONGARCH_VIRT_MACHINE

2024-05-07 Thread Bibo Mao
On LoongArch system, there is only virt machine type now, name
LOONGARCH_MACHINE is confused, rename it with LOONGARCH_VIRT_MACHINE.
Machine name about Other real hw boards can be added in future.

Signed-off-by: Bibo Mao 
---
 hw/loongarch/acpi-build.c   |  8 
 hw/loongarch/boot.c |  2 +-
 hw/loongarch/virt.c | 19 +--
 include/hw/loongarch/virt.h |  4 ++--
 4 files changed, 16 insertions(+), 17 deletions(-)

diff --git a/hw/loongarch/acpi-build.c b/hw/loongarch/acpi-build.c
index e5ab1080af..c7150cc0c4 100644
--- a/hw/loongarch/acpi-build.c
+++ b/hw/loongarch/acpi-build.c
@@ -167,7 +167,7 @@ build_srat(GArray *table_data, BIOSLinker *linker, 
MachineState *machine)
 int i, arch_id, node_id;
 uint64_t mem_len, mem_base;
 int nb_numa_nodes = machine->numa_state->num_nodes;
-LoongArchMachineState *lams = LOONGARCH_MACHINE(machine);
+LoongArchMachineState *lams = LOONGARCH_VIRT_MACHINE(machine);
 MachineClass *mc = MACHINE_GET_CLASS(lams);
 const CPUArchIdList *arch_ids = mc->possible_cpu_arch_ids(machine);
 AcpiTable table = { .sig = "SRAT", .rev = 1, .oem_id = lams->oem_id,
@@ -279,7 +279,7 @@ static void
 build_la_ged_aml(Aml *dsdt, MachineState *machine)
 {
 uint32_t event;
-LoongArchMachineState *lams = LOONGARCH_MACHINE(machine);
+LoongArchMachineState *lams = LOONGARCH_VIRT_MACHINE(machine);
 
 build_ged_aml(dsdt, "\\_SB."GED_DEVICE,
   HOTPLUG_HANDLER(lams->acpi_ged),
@@ -391,7 +391,7 @@ static void
 build_dsdt(GArray *table_data, BIOSLinker *linker, MachineState *machine)
 {
 Aml *dsdt, *scope, *pkg;
-LoongArchMachineState *lams = LOONGARCH_MACHINE(machine);
+LoongArchMachineState *lams = LOONGARCH_VIRT_MACHINE(machine);
 AcpiTable table = { .sig = "DSDT", .rev = 1, .oem_id = lams->oem_id,
 .oem_table_id = lams->oem_table_id };
 
@@ -421,7 +421,7 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, 
MachineState *machine)
 
 static void acpi_build(AcpiBuildTables *tables, MachineState *machine)
 {
-LoongArchMachineState *lams = LOONGARCH_MACHINE(machine);
+LoongArchMachineState *lams = LOONGARCH_VIRT_MACHINE(machine);
 GArray *table_offsets;
 AcpiFadtData fadt_data;
 unsigned facs, rsdt, dsdt;
diff --git a/hw/loongarch/boot.c b/hw/loongarch/boot.c
index 7d1630b2e7..9b4a2d19a9 100644
--- a/hw/loongarch/boot.c
+++ b/hw/loongarch/boot.c
@@ -316,7 +316,7 @@ static void loongarch_direct_kernel_boot(struct 
loongarch_boot_info *info)
 
 void loongarch_load_kernel(MachineState *ms, struct loongarch_boot_info *info)
 {
-LoongArchMachineState *lams = LOONGARCH_MACHINE(ms);
+LoongArchMachineState *lams = LOONGARCH_VIRT_MACHINE(ms);
 int i;
 
 /* register reset function */
diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c
index c0999878df..6619cb52a9 100644
--- a/hw/loongarch/virt.c
+++ b/hw/loongarch/virt.c
@@ -880,7 +880,7 @@ static void loongarch_init(MachineState *machine)
 ram_addr_t ram_size = machine->ram_size;
 uint64_t highram_size = 0, phyAddr = 0;
 MemoryRegion *address_space_mem = get_system_memory();
-LoongArchMachineState *lams = LOONGARCH_MACHINE(machine);
+LoongArchMachineState *lams = LOONGARCH_VIRT_MACHINE(machine);
 int nb_numa_nodes = machine->numa_state->num_nodes;
 NodeInfo *numa_info = machine->numa_state->nodes;
 int i;
@@ -1032,7 +1032,7 @@ bool loongarch_is_acpi_enabled(LoongArchMachineState 
*lams)
 static void loongarch_get_acpi(Object *obj, Visitor *v, const char *name,
void *opaque, Error **errp)
 {
-LoongArchMachineState *lams = LOONGARCH_MACHINE(obj);
+LoongArchMachineState *lams = LOONGARCH_VIRT_MACHINE(obj);
 OnOffAuto acpi = lams->acpi;
 
 visit_type_OnOffAuto(v, name, , errp);
@@ -1041,14 +1041,14 @@ static void loongarch_get_acpi(Object *obj, Visitor *v, 
const char *name,
 static void loongarch_set_acpi(Object *obj, Visitor *v, const char *name,
void *opaque, Error **errp)
 {
-LoongArchMachineState *lams = LOONGARCH_MACHINE(obj);
+LoongArchMachineState *lams = LOONGARCH_VIRT_MACHINE(obj);
 
 visit_type_OnOffAuto(v, name, >acpi, errp);
 }
 
 static void loongarch_machine_initfn(Object *obj)
 {
-LoongArchMachineState *lams = LOONGARCH_MACHINE(obj);
+LoongArchMachineState *lams = LOONGARCH_VIRT_MACHINE(obj);
 
 lams->acpi = ON_OFF_AUTO_AUTO;
 lams->oem_id = g_strndup(ACPI_BUILD_APPNAME6, 6);
@@ -1080,7 +1080,7 @@ static void virt_machine_device_pre_plug(HotplugHandler 
*hotplug_dev,
 static void virt_mem_unplug_request(HotplugHandler *hotplug_dev,
  DeviceState *dev, Error **errp)
 {
-LoongArchMachineState *lams = LOONGARCH_MACHINE(hotplug_dev);
+LoongArchMachineState *lams = LOONGARCH_VIRT_MACHINE(hotplug_dev);
 
 /* the acpi ged is always exist */
 

[PATCH v4 2/5] hw/loongarch: Rename LoongArchMachineState with LoongArchVirtMachineState

2024-05-07 Thread Bibo Mao
Rename LoongArchMachineState with LoongArchVirtMachineState, and change
variable name LoongArchMachineState *lams with LoongArchVirtMachineState
*lvms.

Rename function specific for virtmachine loongarch_xxx()
with virt_xxx(). However some common functions keep unchanged such as
loongarch_acpi_setup()/loongarch_load_kernel(), since there functions
can be used for real hw boards.

Signed-off-by: Bibo Mao 
---
 hw/loongarch/acpi-build.c   |  89 +-
 hw/loongarch/boot.c |  10 +-
 hw/loongarch/fw_cfg.c   |   2 +-
 hw/loongarch/fw_cfg.h   |   2 +-
 hw/loongarch/virt.c | 340 ++--
 include/hw/loongarch/virt.h |   7 +-
 6 files changed, 226 insertions(+), 224 deletions(-)

diff --git a/hw/loongarch/acpi-build.c b/hw/loongarch/acpi-build.c
index c7150cc0c4..5ef010d4da 100644
--- a/hw/loongarch/acpi-build.c
+++ b/hw/loongarch/acpi-build.c
@@ -105,14 +105,15 @@ build_facs(GArray *table_data)
 
 /* build MADT */
 static void
-build_madt(GArray *table_data, BIOSLinker *linker, LoongArchMachineState *lams)
+build_madt(GArray *table_data, BIOSLinker *linker,
+   LoongArchVirtMachineState *lvms)
 {
-MachineState *ms = MACHINE(lams);
+MachineState *ms = MACHINE(lvms);
 MachineClass *mc = MACHINE_GET_CLASS(ms);
 const CPUArchIdList *arch_ids = mc->possible_cpu_arch_ids(ms);
 int i, arch_id;
-AcpiTable table = { .sig = "APIC", .rev = 1, .oem_id = lams->oem_id,
-.oem_table_id = lams->oem_table_id };
+AcpiTable table = { .sig = "APIC", .rev = 1, .oem_id = lvms->oem_id,
+.oem_table_id = lvms->oem_table_id };
 
 acpi_table_begin(, table_data);
 
@@ -167,11 +168,11 @@ build_srat(GArray *table_data, BIOSLinker *linker, 
MachineState *machine)
 int i, arch_id, node_id;
 uint64_t mem_len, mem_base;
 int nb_numa_nodes = machine->numa_state->num_nodes;
-LoongArchMachineState *lams = LOONGARCH_VIRT_MACHINE(machine);
-MachineClass *mc = MACHINE_GET_CLASS(lams);
+LoongArchVirtMachineState *lvms = LOONGARCH_VIRT_MACHINE(machine);
+MachineClass *mc = MACHINE_GET_CLASS(lvms);
 const CPUArchIdList *arch_ids = mc->possible_cpu_arch_ids(machine);
-AcpiTable table = { .sig = "SRAT", .rev = 1, .oem_id = lams->oem_id,
-.oem_table_id = lams->oem_table_id };
+AcpiTable table = { .sig = "SRAT", .rev = 1, .oem_id = lvms->oem_id,
+.oem_table_id = lvms->oem_table_id };
 
 acpi_table_begin(, table_data);
 build_append_int_noprefix(table_data, 1, 4); /* Reserved */
@@ -279,13 +280,13 @@ static void
 build_la_ged_aml(Aml *dsdt, MachineState *machine)
 {
 uint32_t event;
-LoongArchMachineState *lams = LOONGARCH_VIRT_MACHINE(machine);
+LoongArchVirtMachineState *lvms = LOONGARCH_VIRT_MACHINE(machine);
 
 build_ged_aml(dsdt, "\\_SB."GED_DEVICE,
-  HOTPLUG_HANDLER(lams->acpi_ged),
+  HOTPLUG_HANDLER(lvms->acpi_ged),
   VIRT_SCI_IRQ, AML_SYSTEM_MEMORY,
   VIRT_GED_EVT_ADDR);
-event = object_property_get_uint(OBJECT(lams->acpi_ged),
+event = object_property_get_uint(OBJECT(lvms->acpi_ged),
  "ged-event", _abort);
 if (event & ACPI_GED_MEM_HOTPLUG_EVT) {
 build_memory_hotplug_aml(dsdt, machine->ram_slots, "\\_SB", NULL,
@@ -295,7 +296,7 @@ build_la_ged_aml(Aml *dsdt, MachineState *machine)
 acpi_dsdt_add_power_button(dsdt);
 }
 
-static void build_pci_device_aml(Aml *scope, LoongArchMachineState *lams)
+static void build_pci_device_aml(Aml *scope, LoongArchVirtMachineState *lvms)
 {
 struct GPEXConfig cfg = {
 .mmio64.base = VIRT_PCI_MEM_BASE,
@@ -305,13 +306,13 @@ static void build_pci_device_aml(Aml *scope, 
LoongArchMachineState *lams)
 .ecam.base   = VIRT_PCI_CFG_BASE,
 .ecam.size   = VIRT_PCI_CFG_SIZE,
 .irq = VIRT_GSI_BASE + VIRT_DEVICE_IRQS,
-.bus = lams->pci_bus,
+.bus = lvms->pci_bus,
 };
 
 acpi_dsdt_add_gpex(scope, );
 }
 
-static void build_flash_aml(Aml *scope, LoongArchMachineState *lams)
+static void build_flash_aml(Aml *scope, LoongArchVirtMachineState *lvms)
 {
 Aml *dev, *crs;
 MemoryRegion *flash_mem;
@@ -322,11 +323,11 @@ static void build_flash_aml(Aml *scope, 
LoongArchMachineState *lams)
 hwaddr flash1_base;
 hwaddr flash1_size;
 
-flash_mem = pflash_cfi01_get_memory(lams->flash[0]);
+flash_mem = pflash_cfi01_get_memory(lvms->flash[0]);
 flash0_base = flash_mem->addr;
 flash0_size = memory_region_size(flash_mem);
 
-flash_mem = pflash_cfi01_get_memory(lams->flash[1]);
+flash_mem = pflash_cfi01_get_memory(lvms->flash[1]);
 flash1_base = flash_mem->addr;
 flash1_size = memory_region_size(flash_mem);
 
@@ -352,7 +353,7 @@ static void build_flash_aml(Aml *scope, 
LoongArchMachineState *lams)
 }
 
 #ifdef CONFIG_TPM
-static void 

[PATCH v4 5/5] tests: Add migration test for loongarch64

2024-05-07 Thread Bibo Mao
This patch adds migration test support for loongarch64. The test code
comes from aarch64 mostly, only that it booted as bios in qemu since
kernel requires elf format and bios uses binary format.

In addition to providing the binary, this patch also includes the source
code and the build script in tests/migration/loongarch64. So users can
change the source and/or re-compile the binary as they wish.

Signed-off-by: Bibo Mao 
Acked-by: Thomas Huth 
Acked-by: Peter Xu 
Reviewed-by: Fabiano Rosas 
---
 tests/migration/Makefile |  2 +-
 tests/migration/loongarch64/Makefile | 18 +
 tests/migration/loongarch64/a-b-kernel.S | 49 
 tests/migration/loongarch64/a-b-kernel.h | 16 
 tests/migration/migration-test.h |  3 ++
 tests/qtest/meson.build  |  4 ++
 tests/qtest/migration-test.c | 10 +
 7 files changed, 101 insertions(+), 1 deletion(-)
 create mode 100644 tests/migration/loongarch64/Makefile
 create mode 100644 tests/migration/loongarch64/a-b-kernel.S
 create mode 100644 tests/migration/loongarch64/a-b-kernel.h

diff --git a/tests/migration/Makefile b/tests/migration/Makefile
index 13e99b1692..cfebfe23f8 100644
--- a/tests/migration/Makefile
+++ b/tests/migration/Makefile
@@ -5,7 +5,7 @@
 # See the COPYING file in the top-level directory.
 #
 
-TARGET_LIST = i386 aarch64 s390x
+TARGET_LIST = i386 aarch64 s390x loongarch64
 
 SRC_PATH = ../..
 
diff --git a/tests/migration/loongarch64/Makefile 
b/tests/migration/loongarch64/Makefile
new file mode 100644
index 00..5d8719205f
--- /dev/null
+++ b/tests/migration/loongarch64/Makefile
@@ -0,0 +1,18 @@
+# To specify cross compiler prefix, use CROSS_PREFIX=
+#   $ make CROSS_PREFIX=loongarch64-linux-gnu-
+
+.PHONY: all clean
+all: a-b-kernel.h
+
+a-b-kernel.h: loongarch64.kernel
+   echo "$$__note" > $@
+   xxd -i $< | sed -e 's/.*int.*//' >> $@
+
+loongarch64.kernel: loongarch64.elf
+   $(CROSS_PREFIX)objcopy -j .text -O binary $< $@
+
+loongarch64.elf: a-b-kernel.S
+   $(CROSS_PREFIX)gcc -o $@ -nostdlib -Wl,--build-id=none $<
+
+clean:
+   $(RM) *.kernel *.elf
diff --git a/tests/migration/loongarch64/a-b-kernel.S 
b/tests/migration/loongarch64/a-b-kernel.S
new file mode 100644
index 00..cd543345fe
--- /dev/null
+++ b/tests/migration/loongarch64/a-b-kernel.S
@@ -0,0 +1,49 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (c) 2024 Loongson Technology Corporation Limited
+ */
+#include "../migration-test.h"
+
+#define LOONGARCH_CSR_CRMD  0
+#define LOONGARCH_VIRT_UART 0x1FE001E0
+.section .text
+
+.globl  _start
+_start:
+/* output char 'A' to UART16550 */
+li.d$t0, LOONGARCH_VIRT_UART
+li.w$t1, 'A'
+st.b$t1, $t0, 0
+
+/* traverse test memory region */
+li.d$t0, LOONGARCH_TEST_MEM_START
+li.d$t1, LOONGARCH_TEST_MEM_END
+li.d$t2, TEST_MEM_PAGE_SIZE
+li.d$t4, LOONGARCH_VIRT_UART
+li.w$t5, 'B'
+
+clean:
+st.b$zero, $t0, 0
+add.d   $t0,   $t0, $t2
+bne $t0,   $t1, clean
+/* keeps a counter so we can limit the output speed */
+addi.d  $t6,   $zero, 0
+
+mainloop:
+li.d$t0, LOONGARCH_TEST_MEM_START
+
+innerloop:
+ld.bu   $t3, $t0, 0
+addi.w  $t3, $t3, 1
+ext.w.b $t3, $t3
+st.b$t3, $t0, 0
+add.d   $t0, $t0, $t2
+bne $t0, $t1, innerloop
+
+addi.d  $t6, $t6, 1
+andi$t6, $t6, 31
+bnez$t6, mainloop
+
+st.b$t5, $t4, 0
+b   mainloop
+nop
diff --git a/tests/migration/loongarch64/a-b-kernel.h 
b/tests/migration/loongarch64/a-b-kernel.h
new file mode 100644
index 00..b3fe466754
--- /dev/null
+++ b/tests/migration/loongarch64/a-b-kernel.h
@@ -0,0 +1,16 @@
+/* This file is automatically generated from the assembly file in
+* tests/migration/loongarch64. Edit that file and then run "make all"
+* inside tests/migration to update, and then remember to send both
+* the header and the assembler differences in your patch submission.
+*/
+unsigned char loongarch64_kernel[] = {
+  0x0c, 0xc0, 0x3f, 0x14, 0x8c, 0x81, 0x87, 0x03, 0x0d, 0x04, 0x81, 0x03,
+  0x8d, 0x01, 0x00, 0x29, 0x0c, 0x00, 0x04, 0x14, 0x0d, 0x80, 0x0c, 0x14,
+  0x2e, 0x00, 0x00, 0x14, 0x10, 0xc0, 0x3f, 0x14, 0x10, 0x82, 0x87, 0x03,
+  0x11, 0x08, 0x81, 0x03, 0x80, 0x01, 0x00, 0x29, 0x8c, 0xb9, 0x10, 0x00,
+  0x8d, 0xf9, 0xff, 0x5f, 0x12, 0x00, 0xc0, 0x02, 0x0c, 0x00, 0x04, 0x14,
+  0x8f, 0x01, 0x00, 0x2a, 0xef, 0x05, 0x80, 0x02, 0xef, 0x5d, 0x00, 0x00,
+  0x8f, 0x01, 0x00, 0x29, 0x8c, 0xb9, 0x10, 0x00, 0x8d, 0xed, 0xff, 0x5f,
+  0x52, 0x06, 0xc0, 0x02, 0x52, 0x7e, 0x40, 0x03, 0x5f, 0xde, 0xff, 0x47,
+  0x11, 0x02, 0x00, 0x29, 0xff, 0xd7, 0xff, 0x53, 0x00, 0x00, 0x40, 0x03
+};
diff --git a/tests/migration/migration-test.h b/tests/migration/migration-test.h
index 68512c0b1b..f402e48349 100644
--- a/tests/migration/migration-test.h
+++ b/tests/migration/migration-test.h
@@ 

[PATCH v4 3/5] hw/loongarch: Add compat machine for 9.0

2024-05-07 Thread Bibo Mao
Since migration test case requires compat machine type support,
compat machine is added for qemu 9.0 here.

Signed-off-by: Bibo Mao 
---
 hw/loongarch/virt.c | 61 +++--
 1 file changed, 48 insertions(+), 13 deletions(-)

diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c
index 93cdadfb8a..c3bb343574 100644
--- a/hw/loongarch/virt.c
+++ b/hw/loongarch/virt.c
@@ -1236,18 +1236,53 @@ static void virt_class_init(ObjectClass *oc, void *data)
 #endif
 }
 
-static const TypeInfo virt_machine_types[] = {
-{
-.name   = TYPE_LOONGARCH_VIRT_MACHINE,
-.parent = TYPE_MACHINE,
-.instance_size  = sizeof(LoongArchVirtMachineState),
-.class_init = virt_class_init,
-.instance_init  = virt_initfn,
-.interfaces = (InterfaceInfo[]) {
- { TYPE_HOTPLUG_HANDLER },
- { }
-},
-}
+#define DEFINE_VIRT_MACHINE_LATEST(major, minor, latest) \
+static void virt_##major##_##minor##_class_init(ObjectClass *oc, \
+void *data) \
+{ \
+MachineClass *mc = MACHINE_CLASS(oc); \
+virt_machine_##major##_##minor##_options(mc); \
+mc->desc = "QEMU " # major "." # minor " LoongArch Virtual Machine"; \
+if (latest) { \
+mc->alias = "virt"; \
+} \
+} \
+static const TypeInfo machvirt_##major##_##minor##_info = { \
+.name = MACHINE_TYPE_NAME("virt-" # major "." # minor), \
+.parent = TYPE_LOONGARCH_VIRT_MACHINE, \
+.class_init = virt_##major##_##minor##_class_init, \
+}; \
+static void machvirt_machine_##major##_##minor##_init(void) \
+{ \
+type_register_static(_##major##_##minor##_info); \
+} \
+type_init(machvirt_machine_##major##_##minor##_init);
+
+#define DEFINE_VIRT_MACHINE_AS_LATEST(major, minor) \
+DEFINE_VIRT_MACHINE_LATEST(major, minor, true)
+#define DEFINE_VIRT_MACHINE(major, minor) \
+DEFINE_VIRT_MACHINE_LATEST(major, minor, false)
+
+static const TypeInfo virt_machine_info = {
+.name   = TYPE_LOONGARCH_VIRT_MACHINE,
+.parent = TYPE_MACHINE,
+.abstract   = true,
+.instance_size  = sizeof(LoongArchVirtMachineState),
+.class_init = virt_class_init,
+.instance_init  = virt_initfn,
+.interfaces = (InterfaceInfo[]) {
+{ TYPE_HOTPLUG_HANDLER },
+{ }
+},
 };
 
-DEFINE_TYPES(virt_machine_types)
+static void machvirt_machine_init(void)
+{
+type_register_static(_machine_info);
+}
+type_init(machvirt_machine_init);
+
+static void virt_machine_9_0_options(MachineClass *mc)
+{
+}
+DEFINE_VIRT_MACHINE_AS_LATEST(9, 0)
-- 
2.39.3




Re: [PATCH v2 10/15] hw/riscv/riscv-iommu: add ATS support

2024-05-07 Thread Frank Chang
Hi Daniel,

Daniel Henrique Barboza  於 2024年3月8日 週五 上午12:06寫道:
>
> From: Tomasz Jeznach 
>
> Add PCIe Address Translation Services (ATS) capabilities to the IOMMU.
> This will add support for ATS translation requests in Fault/Event
> queues, Page-request queue and IOATC invalidations.
>
> Signed-off-by: Tomasz Jeznach 
> Signed-off-by: Daniel Henrique Barboza 
> ---
>  hw/riscv/riscv-iommu-bits.h |  43 ++-
>  hw/riscv/riscv-iommu.c  | 107 +---
>  hw/riscv/riscv-iommu.h  |   1 +
>  hw/riscv/trace-events   |   3 +
>  4 files changed, 145 insertions(+), 9 deletions(-)
>
> diff --git a/hw/riscv/riscv-iommu-bits.h b/hw/riscv/riscv-iommu-bits.h
> index 9d645d69ea..0994f5ce48 100644
> --- a/hw/riscv/riscv-iommu-bits.h
> +++ b/hw/riscv/riscv-iommu-bits.h
> @@ -81,6 +81,7 @@ struct riscv_iommu_pq_record {
>  #define RISCV_IOMMU_CAP_SV57X4  BIT_ULL(19)
>  #define RISCV_IOMMU_CAP_MSI_FLATBIT_ULL(22)
>  #define RISCV_IOMMU_CAP_MSI_MRIFBIT_ULL(23)
> +#define RISCV_IOMMU_CAP_ATS BIT_ULL(25)
>  #define RISCV_IOMMU_CAP_IGS GENMASK_ULL(29, 28)
>  #define RISCV_IOMMU_CAP_PAS GENMASK_ULL(37, 32)
>  #define RISCV_IOMMU_CAP_PD8 BIT_ULL(38)
> @@ -201,6 +202,7 @@ struct riscv_iommu_dc {
>
>  /* Translation control fields */
>  #define RISCV_IOMMU_DC_TC_V BIT_ULL(0)
> +#define RISCV_IOMMU_DC_TC_EN_ATSBIT_ULL(1)
>  #define RISCV_IOMMU_DC_TC_DTF   BIT_ULL(4)
>  #define RISCV_IOMMU_DC_TC_PDTV  BIT_ULL(5)
>  #define RISCV_IOMMU_DC_TC_PRPR  BIT_ULL(6)
> @@ -259,6 +261,20 @@ struct riscv_iommu_command {
>  #define RISCV_IOMMU_CMD_IODIR_DVBIT_ULL(33)
>  #define RISCV_IOMMU_CMD_IODIR_DID   GENMASK_ULL(63, 40)
>
> +/* 3.1.4 I/O MMU PCIe ATS */
> +#define RISCV_IOMMU_CMD_ATS_OPCODE  4
> +#define RISCV_IOMMU_CMD_ATS_FUNC_INVAL  0
> +#define RISCV_IOMMU_CMD_ATS_FUNC_PRGR   1
> +#define RISCV_IOMMU_CMD_ATS_PID GENMASK_ULL(31, 12)
> +#define RISCV_IOMMU_CMD_ATS_PV  BIT_ULL(32)
> +#define RISCV_IOMMU_CMD_ATS_DSV BIT_ULL(33)
> +#define RISCV_IOMMU_CMD_ATS_RID GENMASK_ULL(55, 40)
> +#define RISCV_IOMMU_CMD_ATS_DSEGGENMASK_ULL(63, 56)
> +/* dword1 is the ATS payload, two different payload types for INVAL and PRGR 
> */
> +
> +/* ATS.PRGR payload */
> +#define RISCV_IOMMU_CMD_ATS_PRGR_RESP_CODE  GENMASK_ULL(47, 44)
> +
>  enum riscv_iommu_dc_fsc_atp_modes {
>  RISCV_IOMMU_DC_FSC_MODE_BARE = 0,
>  RISCV_IOMMU_DC_FSC_IOSATP_MODE_SV32 = 8,
> @@ -322,7 +338,32 @@ enum riscv_iommu_fq_ttypes {
>  RISCV_IOMMU_FQ_TTYPE_TADDR_INST_FETCH = 5,
>  RISCV_IOMMU_FQ_TTYPE_TADDR_RD = 6,
>  RISCV_IOMMU_FQ_TTYPE_TADDR_WR = 7,
> -RISCV_IOMMU_FW_TTYPE_PCIE_MSG_REQ = 8,
> +RISCV_IOMMU_FQ_TTYPE_PCIE_ATS_REQ = 8,
> +RISCV_IOMMU_FW_TTYPE_PCIE_MSG_REQ = 9,
> +};
> +
> +/* Header fields */
> +#define RISCV_IOMMU_PREQ_HDR_PIDGENMASK_ULL(31, 12)
> +#define RISCV_IOMMU_PREQ_HDR_PV BIT_ULL(32)
> +#define RISCV_IOMMU_PREQ_HDR_PRIV   BIT_ULL(33)
> +#define RISCV_IOMMU_PREQ_HDR_EXEC   BIT_ULL(34)
> +#define RISCV_IOMMU_PREQ_HDR_DIDGENMASK_ULL(63, 40)
> +
> +/* Payload fields */
> +#define RISCV_IOMMU_PREQ_PAYLOAD_R  BIT_ULL(0)
> +#define RISCV_IOMMU_PREQ_PAYLOAD_W  BIT_ULL(1)
> +#define RISCV_IOMMU_PREQ_PAYLOAD_L  BIT_ULL(2)
> +#define RISCV_IOMMU_PREQ_PAYLOAD_M  GENMASK_ULL(2, 0)
> +#define RISCV_IOMMU_PREQ_PRG_INDEX  GENMASK_ULL(11, 3)
> +#define RISCV_IOMMU_PREQ_UADDR  GENMASK_ULL(63, 12)
> +
> +
> +/*
> + * struct riscv_iommu_msi_pte - MSI Page Table Entry
> + */
> +struct riscv_iommu_msi_pte {
> +  uint64_t pte;
> +  uint64_t mrif_info;
>  };
>
>  /* Fields on pte */
> diff --git a/hw/riscv/riscv-iommu.c b/hw/riscv/riscv-iommu.c
> index 03a610fa75..7af5929b10 100644
> --- a/hw/riscv/riscv-iommu.c
> +++ b/hw/riscv/riscv-iommu.c
> @@ -576,7 +576,7 @@ static int riscv_iommu_ctx_fetch(RISCVIOMMUState *s, 
> RISCVIOMMUContext *ctx)
>  RISCV_IOMMU_DC_IOHGATP_MODE_BARE);
>  ctx->satp = set_field(0, RISCV_IOMMU_ATP_MODE_FIELD,
>  RISCV_IOMMU_DC_FSC_MODE_BARE);
> -ctx->tc = RISCV_IOMMU_DC_TC_V;
> +ctx->tc = RISCV_IOMMU_DC_TC_EN_ATS | RISCV_IOMMU_DC_TC_V;

We should OR RISCV_IOMMU_DC_TC_EN_ATS only when IOMMU has ATS capability.
(i.e. s->enable_ats == true).

>  ctx->ta = 0;
>  ctx->msiptp = 0;
>  return 0;
> @@ -1021,6 +1021,18 @@ static int riscv_iommu_translate(RISCVIOMMUState *s, 
> RISCVIOMMUContext *ctx,
>  enable_pri = (iotlb->perm == IOMMU_NONE) && (ctx->tc & BIT_ULL(32));
>  enable_pasid = (ctx->tc & RISCV_IOMMU_DC_TC_PDTV);
>
> +/* Check for ATS request. */
> +if (iotlb->perm == IOMMU_NONE) {
> +/* Check if ATS is disabled. */
> +if (!(ctx->tc & RISCV_IOMMU_DC_TC_EN_ATS)) {
> +enable_pri = false;
> +

Re: [PATCH] hw/loongarch/virt: Fix memory leak

2024-05-07 Thread gaosong

在 2024/5/7 下午5:52, Michael Tokarev 写道:

07.05.2024 05:22, Song Gao wrote:


  for (i = 1; i < nb_numa_nodes; i++) {
  MemoryRegion *nodemem = g_new(MemoryRegion, 1);
-    ramName = g_strdup_printf("loongarch.node%d.ram", i);
+    g_autofree char *ramName = 
g_strdup_printf("loongarch.node%d.ram", i);


Can't this be a fixed-size buffer on stack?

Maybe I'm old-minded, but such obviously fixed and
very small allocations on the heap hurt my eyes ;)


I had send v2 patch.

Thanks.
Song Gao

/mjt





[PATCH v2] target/loongarch/kvm: Fix VM recovery from disk failures

2024-05-07 Thread Song Gao
vmstate does not save kvm_state_conter,
which can cause VM recovery from disk to fail.

Signed-off-by: Song Gao 
---
v2:
  - Update the version.
  - Link to v1: 
https://patchew.org/QEMU/20240430012356.2620763-1-gaos...@loongson.cn/
 target/loongarch/machine.c | 6 --
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/target/loongarch/machine.c b/target/loongarch/machine.c
index c7029fb9b4..d6109e3b20 100644
--- a/target/loongarch/machine.c
+++ b/target/loongarch/machine.c
@@ -125,8 +125,8 @@ const VMStateDescription vmstate_tlb = {
 /* LoongArch CPU state */
 const VMStateDescription vmstate_loongarch_cpu = {
 .name = "cpu",
-.version_id = 1,
-.minimum_version_id = 1,
+.version_id = 2,
+.minimum_version_id = 2,
 .fields = (const VMStateField[]) {
 VMSTATE_UINTTL_ARRAY(env.gpr, LoongArchCPU, 32),
 VMSTATE_UINTTL(env.pc, LoongArchCPU),
@@ -191,6 +191,8 @@ const VMStateDescription vmstate_loongarch_cpu = {
 VMSTATE_STRUCT_ARRAY(env.tlb, LoongArchCPU, LOONGARCH_TLB_MAX,
  0, vmstate_tlb, LoongArchTLB),
 
+VMSTATE_UINT64(kvm_state_counter, LoongArchCPU),
+
 VMSTATE_END_OF_LIST()
 },
 .subsections = (const VMStateDescription * const []) {
-- 
2.25.1




[PATCH v2] hw/loongarch/virt: Fix memory leak

2024-05-07 Thread Song Gao
The char pointer 'ramName' point to a block of memory, but never free it.
Use a small fixed-size buffer for 'ramName'.

Resolves: Coverity CID 1544773

Fixes: 0cf1478d6 ("hw/loongarch: Add numa support")
Signed-off-by: Song Gao 
---
v2:
  - Use a small fixed-size buffer for 'ramName'.
  - Link to V1: 
https://patchew.org/QEMU/20240507022239.3113987-1-gaos...@loongson.cn/ 

 hw/loongarch/virt.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c
index c0999878df..ee690ad981 100644
--- a/hw/loongarch/virt.c
+++ b/hw/loongarch/virt.c
@@ -887,7 +887,7 @@ static void loongarch_init(MachineState *machine)
 const CPUArchIdList *possible_cpus;
 MachineClass *mc = MACHINE_GET_CLASS(machine);
 CPUState *cpu;
-char *ramName = NULL;
+char ramName[32];
 
 if (!cpu_model) {
 cpu_model = LOONGARCH_CPU_TYPE_NAME("la464");
@@ -946,7 +946,7 @@ static void loongarch_init(MachineState *machine)
 
 for (i = 1; i < nb_numa_nodes; i++) {
 MemoryRegion *nodemem = g_new(MemoryRegion, 1);
-ramName = g_strdup_printf("loongarch.node%d.ram", i);
+sprintf(ramName, "loongarch.node%d.ram", i);
 memory_region_init_alias(nodemem, NULL, ramName, machine->ram,
  offset,  numa_info[i].node_mem);
 memory_region_add_subregion(address_space_mem, phyAddr, nodemem);
-- 
2.25.1




Re: [RFC 0/2] Identify aliased maps in vdpa SVQ iova_tree

2024-05-07 Thread Jason Wang
On Tue, May 7, 2024 at 6:57 PM Eugenio Perez Martin  wrote:
>
> On Tue, May 7, 2024 at 9:29 AM Jason Wang  wrote:
> >
> > On Fri, Apr 12, 2024 at 3:56 PM Eugenio Perez Martin
> >  wrote:
> > >
> > > On Fri, Apr 12, 2024 at 8:47 AM Jason Wang  wrote:
> > > >
> > > > On Wed, Apr 10, 2024 at 6:03 PM Eugenio Pérez  
> > > > wrote:
> > > > >
> > > > > The guest may have overlapped memory regions, where different GPA 
> > > > > leads
> > > > > to the same HVA.  This causes a problem when overlapped regions
> > > > > (different GPA but same translated HVA) exists in the tree, as looking
> > > > > them by HVA will return them twice.
> > > >
> > > > I think I don't understand if there's any side effect for shadow 
> > > > virtqueue?
> > > >
> > >
> > > My bad, I totally forgot to put a reference to where this comes from.
> > >
> > > Si-Wei found that during initialization this sequences of maps /
> > > unmaps happens [1]:
> > >
> > > HVAGPAIOVA
> > > -
> > > Map
> > > [0x7f7903e0, 0x7f7983e0)[0x0, 0x8000) [0x1000, 0x8000)
> > > [0x7f7983e0, 0x7f9903e0)[0x1, 0x208000)
> > > [0x80001000, 0x201000)
> > > [0x7f7903ea, 0x7f7903ec)[0xfeda, 0xfedc)
> > > [0x201000, 0x221000)
> > >
> > > Unmap
> > > [0x7f7903ea, 0x7f7903ec)[0xfeda, 0xfedc) [0x1000,
> > > 0x2) ???
> > >
> > > The third HVA range is contained in the first one, but exposed under a
> > > different GVA (aliased). This is not "flattened" by QEMU, as GPA does
> > > not overlap, only HVA.
> > >
> > > At the third chunk unmap, the current algorithm finds the first chunk,
> > > not the second one. This series is the way to tell the difference at
> > > unmap time.
> > >
> > > [1] https://lists.nongnu.org/archive/html/qemu-devel/2024-04/msg00079.html
> > >
> > > Thanks!
> >
> > Ok, I was wondering if we need to store GPA(GIOVA) to HVA mappings in
> > the iova tree to solve this issue completely. Then there won't be
> > aliasing issues.
> >
>
> I'm ok to explore that route but this has another problem. Both SVQ
> vrings and CVQ buffers also need to be addressable by VhostIOVATree,
> and they do not have GPA.
>
> At this moment vhost_svq_translate_addr is able to handle this
> transparently as we translate vaddr to SVQ IOVA. How can we store
> these new entries? Maybe a (hwaddr)-1 GPA to signal it has no GPA and
> then a list to go through other entries (SVQ vaddr and CVQ buffers).

This seems to be tricky.

As discussed, it could be another iova tree.

Thanks

>
> Thanks!
>
> > Thanks
> >
> > >
> > > > Thanks
> > > >
> > > > >
> > > > > To solve this, track GPA in the DMA entry that acs as unique 
> > > > > identifiers
> > > > > to the maps.  When the map needs to be removed, iova tree is able to
> > > > > find the right one.
> > > > >
> > > > > Users that does not go to this extra layer of indirection can use the
> > > > > iova tree as usual, with id = 0.
> > > > >
> > > > > This was found by Si-Wei Liu , but I'm having 
> > > > > a hard
> > > > > time to reproduce the issue.  This has been tested only without 
> > > > > overlapping
> > > > > maps.  If it works with overlapping maps, it will be intergrated in 
> > > > > the main
> > > > > series.
> > > > >
> > > > > Comments are welcome.  Thanks!
> > > > >
> > > > > Eugenio Pérez (2):
> > > > >   iova_tree: add an id member to DMAMap
> > > > >   vdpa: identify aliased maps in iova_tree
> > > > >
> > > > >  hw/virtio/vhost-vdpa.c   | 2 ++
> > > > >  include/qemu/iova-tree.h | 5 +++--
> > > > >  util/iova-tree.c | 3 ++-
> > > > >  3 files changed, 7 insertions(+), 3 deletions(-)
> > > > >
> > > > > --
> > > > > 2.44.0
> > > > >
> > > >
> > >
> >
>




[PATCH v3] mem/cxl_type3: support 3, 6, 12 and 16 interleave ways

2024-05-07 Thread Yao Xingtao via
Since the kernel does not check the interleave capability, a
3-way, 6-way, 12-way or 16-way region can be create normally.

Applications can access the memory of 16-way region normally because
qemu can convert hpa to dpa correctly for the power of 2 interleave
ways, after kernel implementing the check, this kind of region will
not be created any more.

For non power of 2 interleave ways, applications could not access the
memory normally and may occur some unexpected behaviors, such as
segmentation fault.

So implements this feature is needed.

Link: 
https://lore.kernel.org/linux-cxl/3e84b919-7631-d1db-3e1d-33000f3f3...@fujitsu.com/
Signed-off-by: Yao Xingtao 
---
 hw/cxl/cxl-component-utils.c |  9 +++--
 hw/mem/cxl_type3.c   | 15 +++
 2 files changed, 18 insertions(+), 6 deletions(-)

diff --git a/hw/cxl/cxl-component-utils.c b/hw/cxl/cxl-component-utils.c
index cd116c0401..473895948b 100644
--- a/hw/cxl/cxl-component-utils.c
+++ b/hw/cxl/cxl-component-utils.c
@@ -243,8 +243,13 @@ static void hdm_init_common(uint32_t *reg_state, uint32_t 
*write_msk,
 ARRAY_FIELD_DP32(reg_state, CXL_HDM_DECODER_CAPABILITY, INTERLEAVE_4K, 1);
 ARRAY_FIELD_DP32(reg_state, CXL_HDM_DECODER_CAPABILITY,
  POISON_ON_ERR_CAP, 0);
-ARRAY_FIELD_DP32(reg_state, CXL_HDM_DECODER_CAPABILITY, 3_6_12_WAY, 0);
-ARRAY_FIELD_DP32(reg_state, CXL_HDM_DECODER_CAPABILITY, 16_WAY, 0);
+if (type == CXL2_TYPE3_DEVICE) {
+ARRAY_FIELD_DP32(reg_state, CXL_HDM_DECODER_CAPABILITY, 3_6_12_WAY, 1);
+ARRAY_FIELD_DP32(reg_state, CXL_HDM_DECODER_CAPABILITY, 16_WAY, 1);
+} else {
+ARRAY_FIELD_DP32(reg_state, CXL_HDM_DECODER_CAPABILITY, 3_6_12_WAY, 0);
+ARRAY_FIELD_DP32(reg_state, CXL_HDM_DECODER_CAPABILITY, 16_WAY, 0);
+}
 ARRAY_FIELD_DP32(reg_state, CXL_HDM_DECODER_CAPABILITY, UIO, 0);
 ARRAY_FIELD_DP32(reg_state, CXL_HDM_DECODER_CAPABILITY,
  UIO_DECODER_COUNT, 0);
diff --git a/hw/mem/cxl_type3.c b/hw/mem/cxl_type3.c
index 3e42490b6c..b755318838 100644
--- a/hw/mem/cxl_type3.c
+++ b/hw/mem/cxl_type3.c
@@ -804,10 +804,17 @@ static bool cxl_type3_dpa(CXLType3Dev *ct3d, hwaddr 
host_addr, uint64_t *dpa)
 continue;
 }
 
-*dpa = dpa_base +
-((MAKE_64BIT_MASK(0, 8 + ig) & hpa_offset) |
- ((MAKE_64BIT_MASK(8 + ig + iw, 64 - 8 - ig - iw) & hpa_offset)
-  >> iw));
+if (iw < 8) {
+*dpa = dpa_base +
+((MAKE_64BIT_MASK(0, 8 + ig) & hpa_offset) |
+ ((MAKE_64BIT_MASK(8 + ig + iw, 64 - 8 - ig - iw) & hpa_offset)
+  >> iw));
+} else {
+*dpa = dpa_base +
+((MAKE_64BIT_MASK(0, 8 + ig) & hpa_offset) |
+ MAKE_64BIT_MASK(ig + iw, 64 - ig - iw) & hpa_offset)
+   >> (ig + iw)) / 3) << (ig + 8)));
+}
 
 return true;
 }
-- 
2.37.3




RE: [PATCH v2] mem/cxl_type3: support 3, 6, 12 and 16 interleave ways

2024-05-07 Thread Xingtao Yao (Fujitsu)



> -Original Message-
> From: Jonathan Cameron 
> Sent: Wednesday, May 8, 2024 12:31 AM
> To: Yao, Xingtao/姚 幸涛 
> Cc: fan...@samsung.com; qemu-devel@nongnu.org
> Subject: Re: [PATCH v2] mem/cxl_type3: support 3, 6, 12 and 16 interleave ways
> 
> On Tue, 7 May 2024 00:22:00 +
> "Xingtao Yao (Fujitsu)"  wrote:
> 
> > > -Original Message-
> > > From: Jonathan Cameron 
> > > Sent: Tuesday, April 30, 2024 10:43 PM
> > > To: Yao, Xingtao/姚 幸涛 
> > > Cc: fan...@samsung.com; qemu-devel@nongnu.org
> > > Subject: Re: [PATCH v2] mem/cxl_type3: support 3, 6, 12 and 16 interleave
> ways
> > >
> > > On Wed, 24 Apr 2024 01:36:56 +
> > > "Xingtao Yao (Fujitsu)"  wrote:
> > >
> > > > ping.
> > > >
> > > > > -Original Message-
> > > > > From: Yao Xingtao 
> > > > > Sent: Sunday, April 7, 2024 11:07 AM
> > > > > To: jonathan.came...@huawei.com; fan...@samsung.com
> > > > > Cc: qemu-devel@nongnu.org; Yao, Xingtao/姚 幸涛
> > > 
> > > > > Subject: [PATCH v2] mem/cxl_type3: support 3, 6, 12 and 16 interleave
> ways
> > > > >
> > > > > Since the kernel does not check the interleave capability, a
> > > > > 3-way, 6-way, 12-way or 16-way region can be create normally.
> > > > >
> > > > > Applications can access the memory of 16-way region normally because
> > > > > qemu can convert hpa to dpa correctly for the power of 2 interleave
> > > > > ways, after kernel implementing the check, this kind of region will
> > > > > not be created any more.
> > > > >
> > > > > For non power of 2 interleave ways, applications could not access the
> > > > > memory normally and may occur some unexpected behaviors, such as
> > > > > segmentation fault.
> > > > >
> > > > > So implements this feature is needed.
> > > > >
> > > > > Link:
> > > > >
> > >
> https://lore.kernel.org/linux-cxl/3e84b919-7631-d1db-3e1d-33000f3f3868@fujits
> > > > > u.com/
> > > > > Signed-off-by: Yao Xingtao 
> > > > > ---
> > > > >  hw/mem/cxl_type3.c | 18 ++
> > > > >  1 file changed, 14 insertions(+), 4 deletions(-)
> > > > >
> > > > > diff --git a/hw/mem/cxl_type3.c b/hw/mem/cxl_type3.c
> > > > > index b0a7e9f11b..d6ef784e96 100644
> > > > > --- a/hw/mem/cxl_type3.c
> > > > > +++ b/hw/mem/cxl_type3.c
> > > > > @@ -805,10 +805,17 @@ static bool cxl_type3_dpa(CXLType3Dev *ct3d,
> > > hwaddr
> > > > > host_addr, uint64_t *dpa)
> > > > >  continue;
> > > > >  }
> > > > >
> > > > > -*dpa = dpa_base +
> > > > > -((MAKE_64BIT_MASK(0, 8 + ig) & hpa_offset) |
> > > > > - ((MAKE_64BIT_MASK(8 + ig + iw, 64 - 8 - ig - iw) &
> hpa_offset)
> > > > > -  >> iw));
> > > > > +if (iw < 8) {
> > > > > +*dpa = dpa_base +
> > > > > +((MAKE_64BIT_MASK(0, 8 + ig) & hpa_offset) |
> > > > > + ((MAKE_64BIT_MASK(8 + ig + iw, 64 - 8 - ig - iw) &
> > > hpa_offset)
> > > > > +  >> iw));
> > > > > +} else {
> > > > > +*dpa = dpa_base +
> > > > > +((MAKE_64BIT_MASK(0, 8 + ig) & hpa_offset) |
> > > > > + MAKE_64BIT_MASK(ig + iw, 64 - ig - iw) &
> hpa_offset)
> > > > > +   >> (ig + iw)) / 3) << (ig + 8)));
> > > > > +}
> > > > >
> > > > >  return true;
> > > > >  }
> > > > > @@ -906,6 +913,9 @@ static void ct3d_reset(DeviceState *dev)
> > > > >  uint32_t *write_msk =
> > > ct3d->cxl_cstate.crb.cache_mem_regs_write_mask;
> > > > >
> > > > >  cxl_component_register_init_common(reg_state, write_msk,
> > > > > CXL2_TYPE3_DEVICE);
> > > > > +ARRAY_FIELD_DP32(reg_state,
> CXL_HDM_DECODER_CAPABILITY,
> > > > > 3_6_12_WAY, 1);
> > > > > +ARRAY_FIELD_DP32(reg_state,
> CXL_HDM_DECODER_CAPABILITY,
> > > > > 16_WAY, 1);
> > > > > +
> > >
> > > Why here rather than in hdm_reg_init_common()?
> > > It's constant data and is currently being set to 0 in there.
> >
> > according to the CXL specifications (8.2.4.20.1 CXL HDM Decoder Capability
> Register (Offset 00h)),
> > this feature is only applicable to cxl.mem, upstream switch port and CXL 
> > host
> bridges shall hardwrite
> > these bits to 0.
> >
> > so I think it would be more appropriate to set these bits here.
> I don't follow. hdm_init_common() (sorry wrong function name above)
> has some type specific stuff already to show how this can be done.
> I'd prefer to minimize what we set directly in the ct3d_reset() call
> because it loses the connection to the rest of the register setup.
thanks, got it.
> 
> Jonathan
> 
> 
> 
> Jonathan
> 
> 
> >
> > >
> > > > >  cxl_device_register_init_t3(ct3d);
> > > > >
> > > > >  /*
> > > > > --
> > > > > 2.37.3
> > > >
> >




Re: [RFC 1/2] iova_tree: add an id member to DMAMap

2024-05-07 Thread Si-Wei Liu




On 5/1/2024 11:44 PM, Eugenio Perez Martin wrote:

On Thu, May 2, 2024 at 1:16 AM Si-Wei Liu  wrote:



On 4/30/2024 10:19 AM, Eugenio Perez Martin wrote:

On Tue, Apr 30, 2024 at 7:55 AM Si-Wei Liu  wrote:


On 4/29/2024 1:14 AM, Eugenio Perez Martin wrote:

On Thu, Apr 25, 2024 at 7:44 PM Si-Wei Liu  wrote:

On 4/24/2024 12:33 AM, Eugenio Perez Martin wrote:

On Wed, Apr 24, 2024 at 12:21 AM Si-Wei Liu  wrote:

On 4/22/2024 1:49 AM, Eugenio Perez Martin wrote:

On Sat, Apr 20, 2024 at 1:50 AM Si-Wei Liu  wrote:

On 4/19/2024 1:29 AM, Eugenio Perez Martin wrote:

On Thu, Apr 18, 2024 at 10:46 PM Si-Wei Liu  wrote:

On 4/10/2024 3:03 AM, Eugenio Pérez wrote:

IOVA tree is also used to track the mappings of virtio-net shadow
virtqueue.  This mappings may not match with the GPA->HVA ones.

This causes a problem when overlapped regions (different GPA but same
translated HVA) exists in the tree, as looking them by HVA will return
them twice.  To solve this, create an id member so we can assign unique
identifiers (GPA) to the maps.

Signed-off-by: Eugenio Pérez 
---
include/qemu/iova-tree.h | 5 +++--
util/iova-tree.c | 3 ++-
2 files changed, 5 insertions(+), 3 deletions(-)

diff --git a/include/qemu/iova-tree.h b/include/qemu/iova-tree.h
index 2a10a7052e..34ee230e7d 100644
--- a/include/qemu/iova-tree.h
+++ b/include/qemu/iova-tree.h
@@ -36,6 +36,7 @@ typedef struct DMAMap {
hwaddr iova;
hwaddr translated_addr;
hwaddr size;/* Inclusive */
+uint64_t id;
IOMMUAccessFlags perm;
} QEMU_PACKED DMAMap;
typedef gboolean (*iova_tree_iterator)(DMAMap *map);
@@ -100,8 +101,8 @@ const DMAMap *iova_tree_find(const IOVATree *tree, const 
DMAMap *map);
 * @map: the mapping to search
 *
 * Search for a mapping in the iova tree that translated_addr overlaps 
with the
- * mapping range specified.  Only the first found mapping will be
- * returned.
+ * mapping range specified and map->id is equal.  Only the first found
+ * mapping will be returned.
 *
 * Return: DMAMap pointer if found, or NULL if not found.  Note that
 * the returned DMAMap pointer is maintained internally.  User should
diff --git a/util/iova-tree.c b/util/iova-tree.c
index 536789797e..0863e0a3b8 100644
--- a/util/iova-tree.c
+++ b/util/iova-tree.c
@@ -97,7 +97,8 @@ static gboolean iova_tree_find_address_iterator(gpointer key, 
gpointer value,

needle = args->needle;
if (map->translated_addr + map->size < needle->translated_addr ||
-needle->translated_addr + needle->size < map->translated_addr) {
+needle->translated_addr + needle->size < map->translated_addr ||
+needle->id != map->id) {

It looks this iterator can also be invoked by SVQ from
vhost_svq_translate_addr() -> iova_tree_find_iova(), where guest GPA
space will be searched on without passing in the ID (GPA), and exact
match for the same GPA range is not actually needed unlike the mapping
removal case. Could we create an API variant, for the SVQ lookup case
specifically? Or alternatively, add a special flag, say skip_id_match to
DMAMap, and the id match check may look like below:

(!needle->skip_id_match && needle->id != map->id)

I think vhost_svq_translate_addr() could just call the API variant or
pass DMAmap with skip_id_match set to true to svq_iova_tree_find_iova().


I think you're totally right. But I'd really like to not complicate
the API of the iova_tree more.

I think we can look for the hwaddr using memory_region_from_host and
then get the hwaddr. It is another lookup though...

Yeah, that will be another means of doing translation without having to
complicate the API around iova_tree. I wonder how the lookup through
memory_region_from_host() may perform compared to the iova tree one, the
former looks to be an O(N) linear search on a linked list while the
latter would be roughly O(log N) on an AVL tree?

Even worse, as the reverse lookup (from QEMU vaddr to SVQ IOVA) is
linear too. It is not even ordered.

Oh Sorry, I misread the code and I should look for g_tree_foreach ()
instead of g_tree_search_node(). So the former is indeed linear
iteration, but it looks to be ordered?

https://github.com/GNOME/glib/blob/main/glib/gtree.c#L1115

The GPA / IOVA are ordered but we're looking by QEMU's vaddr.

If we have these translations:
[0x1000, 0x2000] -> [0x1, 0x11000]
[0x2000, 0x3000] -> [0x6000, 0x7000]

We will see them in this order, so we cannot stop the search at the first node.

Yeah, reverse lookup is unordered indeed, anyway.


But apart from this detail you're right, I have the same concerns with
this solution too. If we see a hard performance regression we could go
to more complicated solutions, like maintaining a reverse IOVATree in
vhost-iova-tree too. First RFCs of SVQ did that actually.

Agreed, yeap we can use memory_region_from_host for now.  Any reason why
reverse 

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

2024-05-07 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 
---
 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 960751a50e..b5d7aeed4e 100644
--- a/target/ppc/mmu-hash32.c
+++ b/target/ppc/mmu-hash32.c
@@ -347,7 +347,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. */
@@ -361,13 +360,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;
@@ -435,7 +432,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 v3 29/33] target/ppc: Remove id_tlbs flag from CPU env

2024-05-07 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 |  1 -
 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, 10 insertions(+), 35 deletions(-)

diff --git a/hw/ppc/pegasos2.c b/hw/ppc/pegasos2.c
index 04d6decb2b..dfc6fab180 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 (cpu->env.tlb_type == TLB_6XX) {
 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..21e12a4f0d 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 */
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 register_6xx_7xx_soft_tlb(CPUPPCState *env, int 
nb_tlbs, int nb_ways)
 #if !defined(CONFIG_USER_ONLY)
 env->nb_tlb = nb_tlbs;
 env->nb_ways = nb_ways;
-env->id_tlbs = 1;
 env->tlb_type = TLB_6XX;
 spr_register(env, SPR_DMISS, "DMISS",
  SPR_NOACCESS, SPR_NOACCESS,
diff --git a/target/ppc/mmu_common.c b/target/ppc/mmu_common.c
index 

[PATCH v3 25/33] target/ppc/mmu_common.c: Remove BookE handling from get_physical_address_wtlb()

2024-05-07 Thread BALATON Zoltan
This function is no longer called for BookE MMU model so remove parts
related to it. This has uncovered a few may be used uninitialised
warnings that are also fixed.

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

diff --git a/target/ppc/mmu_common.c b/target/ppc/mmu_common.c
index 83dc041a77..788e2bebd5 100644
--- a/target/ppc/mmu_common.c
+++ b/target/ppc/mmu_common.c
@@ -629,12 +629,10 @@ static int mmubooke_get_physical_address(CPUPPCState 
*env, mmu_ctx_t *ctx,
 ret = mmubooke_check_tlb(env, tlb, , >prot, address,
  access_type, i);
 if (ret != -1) {
-if (ret >= 0) {
-ctx->raddr = raddr;
-}
 break;
 }
 }
+ctx->raddr = raddr;
 qemu_log_mask(CPU_LOG_MMU,
   "%s: access %s " TARGET_FMT_lx " => " HWADDR_FMT_plx
   " %d %d\n", __func__, ret < 0 ? "refused" : "granted",
@@ -841,9 +839,6 @@ static int mmubooke206_get_physical_address(CPUPPCState 
*env, mmu_ctx_t *ctx,
 ret = mmubooke206_check_tlb(env, tlb, , >prot, address,
 access_type, mmu_idx);
 if (ret != -1) {
-if (ret >= 0) {
-ctx->raddr = raddr;
-}
 goto found_tlb;
 }
 }
@@ -851,6 +846,7 @@ static int mmubooke206_get_physical_address(CPUPPCState 
*env, mmu_ctx_t *ctx,
 
 found_tlb:
 
+ctx->raddr = raddr;
 qemu_log_mask(CPU_LOG_MMU, "%s: access %s " TARGET_FMT_lx " => "
   HWADDR_FMT_plx " %d %d\n", __func__,
   ret < 0 ? "refused" : "granted", address, raddr,
@@ -1107,20 +1103,9 @@ static 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, 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);
-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) {
 memset(ctx, 0, sizeof(*ctx));
 ctx->raddr = eaddr;
 ctx->prot = PAGE_RWX;
-- 
2.30.9




[PATCH v3 13/33] target/ppc/mmu_common.c: Split out BookE cases before checking real mode

2024-05-07 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 2b6252f3f9..5a0df60ebc 100644
--- a/target/ppc/mmu_common.c
+++ b/target/ppc/mmu_common.c
@@ -1178,6 +1178,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);
 
@@ -1198,13 +1205,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 v3 33/33] target/ppc: Add a macro to check for page protection bit

2024-05-07 Thread BALATON Zoltan
Checking if a page protection bit is set for a given access type is a
common operation. Add a macro to avoid repeating the same check at
multiple places and also avoid a function call. 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|  4 
 target/ppc/internal.h| 20 ++--
 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, 24 insertions(+), 36 deletions(-)

diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c
index 92c71b2a09..6639235544 100644
--- a/target/ppc/cpu_init.c
+++ b/target/ppc/cpu_init.c
@@ -7377,6 +7377,10 @@ static void ppc_cpu_class_init(ObjectClass *oc, void 
*data)
 resettable_class_set_parent_phases(rc, NULL, ppc_cpu_reset_hold, NULL,
>parent_phases);
 
+/* CHECK_PROT_ACCESS relies on this MMU access and PAGE bits relation */
+assert(MMU_DATA_LOAD == 0 && MMU_DATA_STORE == 1 && MMU_INST_FETCH == 2 &&
+   PAGE_READ == 1 && PAGE_WRITE == 2 && PAGE_EXEC == 4);
+
 cc->class_by_name = ppc_cpu_class_by_name;
 cc->has_work = ppc_cpu_has_work;
 cc->mmu_index = ppc_cpu_mmu_index;
diff --git a/target/ppc/internal.h b/target/ppc/internal.h
index 46176c4711..9880422ce3 100644
--- a/target/ppc/internal.h
+++ b/target/ppc/internal.h
@@ -234,24 +234,8 @@ 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)
-{
-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();
-}
+/* Check if permission bit required for the access_type is set in prot */
+#define CHECK_PROT_ACCESS(prot, access_type) ((prot) & (1 << (access_type)))
 
 #ifndef CONFIG_USER_ONLY
 
diff --git a/target/ppc/mmu-hash32.c b/target/ppc/mmu-hash32.c
index b5d7aeed4e..fa4a4ced6d 100644
--- a/target/ppc/mmu-hash32.c
+++ b/target/ppc/mmu-hash32.c
@@ -213,7 +213,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(*prot, access_type)) {
 *raddr = eaddr;
 return true;
 }
@@ -364,7 +364,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(*protp, access_type)) {
 if (guest_visible) {
 if (access_type == MMU_INST_FETCH) {
 cs->exception_index = POWERPC_EXCP_ISI;
@@ -432,7 +432,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(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 5a0d80feda..14c2116ae7 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(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..a72cd927c4 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(*prot, access_type)) {
 /* Page Protected for that Access */
 *fault_cause |= access_type == MMU_INST_FETCH ? SRR1_NOEXEC_GUARD :
 DSISR_PROTFAULT;
diff --git a/target/ppc/mmu_common.c b/target/ppc/mmu_common.c

[PATCH v3 17/33] target/ppc/mmu_common.c: Simplify mmubooke206_get_physical_address()

2024-05-07 Thread BALATON Zoltan
This function is similar to mmubooke_get_physical_address() and can be
simplified the same way.

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

diff --git a/target/ppc/mmu_common.c b/target/ppc/mmu_common.c
index 9793e6d282..a5bc747f40 100644
--- a/target/ppc/mmu_common.c
+++ b/target/ppc/mmu_common.c
@@ -859,15 +859,11 @@ static int mmubooke206_get_physical_address(CPUPPCState 
*env, mmu_ctx_t *ctx,
 int mmu_idx)
 {
 ppcmas_tlb_t *tlb;
-hwaddr raddr;
-int i, j, ret;
-
-ret = -1;
-raddr = (hwaddr)-1ULL;
+hwaddr 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) {
@@ -876,6 +872,9 @@ static int mmubooke206_get_physical_address(CPUPPCState 
*env, mmu_ctx_t *ctx,
 ret = mmubooke206_check_tlb(env, tlb, , >prot, address,
 access_type, mmu_idx);
 if (ret != -1) {
+if (ret >= 0) {
+ctx->raddr = raddr;
+}
 goto found_tlb;
 }
 }
@@ -883,17 +882,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, raddr,
+  ctx->prot, ret);
 return ret;
 }
 
-- 
2.30.9




[PATCH v3 10/33] target/ppc/mmu_common.c: Move else branch to avoid large if block

2024-05-07 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 
---
 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 181273579b..9d337a73ba 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 v3 30/33] target/ppc: Split off common embedded TLB init

2024-05-07 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 v3 27/33] target/ppc/mmu_common.c: Simplify ppc_booke_xlate() part 2

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

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

diff --git a/target/ppc/mmu_common.c b/target/ppc/mmu_common.c
index c725a7932f..04e5ad661d 100644
--- a/target/ppc/mmu_common.c
+++ b/target/ppc/mmu_common.c
@@ -1206,45 +1206,35 @@ 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;
+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;
-case -2:
-/* Access rights violation */
-cs->exception_index = POWERPC_EXCP_ISI;
-break;
-case -3:
-/* No execute protection violation */
+}
+break;
+case -3:
+/* No execute protection violation */
+if (access_type == MMU_INST_FETCH) {
 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;
-env->spr[SPR_BOOKE_DEAR] = eaddr;
-env->spr[SPR_BOOKE_ESR] = mmubooke206_esr(mmu_idx, access_type);
-break;
 }
+break;
 }
+
 return false;
 }
 
-- 
2.30.9




[PATCH v3 12/33] target/ppc/mmu_common.c: Eliminate ret from mmu6xx_get_physical_address()

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

Signed-off-by: BALATON Zoltan 
---
 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 b2f2cee1a8..2b6252f3f9 100644
--- a/target/ppc/mmu_common.c
+++ b/target/ppc/mmu_common.c
@@ -389,7 +389,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) {
@@ -422,7 +421,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) {
@@ -439,51 +437,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 v3 21/33] target/ppc/mmu_common.c: Make get_physical_address_wtlb() static

2024-05-07 Thread BALATON Zoltan
This function is not used from any other files so make it static and
fix the maybe used uninitialised warnings this has uncovered. Also
remove mmu_ctx_t definition from internal.h as this type is only used
within this file.

Signed-off-by: BALATON Zoltan 
---
 target/ppc/internal.h   | 17 +
 target/ppc/mmu_common.c | 18 +++---
 2 files changed, 16 insertions(+), 19 deletions(-)

diff --git a/target/ppc/internal.h b/target/ppc/internal.h
index 98b41a970c..4a90dd2584 100644
--- a/target/ppc/internal.h
+++ b/target/ppc/internal.h
@@ -257,28 +257,13 @@ 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);
-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);
-/* 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 63b5fb98d1..d92c9607b8 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);
@@ -667,7 +678,7 @@ static int mmubooke_get_physical_address(CPUPPCState *env, 
mmu_ctx_t *ctx,
 qemu_log_mask(CPU_LOG_MMU,
   "%s: access %s " TARGET_FMT_lx " => " HWADDR_FMT_plx
   " %d %d\n", __func__, ret < 0 ? "refused" : "granted",
-  address, raddr, ctx->prot, ret);
+  address, raddr, ret == -1 ? 0 : ctx->prot, ret);
 return ret;
 }
 
@@ -883,7 +894,7 @@ found_tlb:
 qemu_log_mask(CPU_LOG_MMU, "%s: access %s " TARGET_FMT_lx " => "
   HWADDR_FMT_plx " %d %d\n", __func__,
   ret < 0 ? "refused" : "granted", address, raddr,
-  ctx->prot, ret);
+  ret == -1 ? 0 : ctx->prot, ret);
 return ret;
 }
 
@@ -1131,7 +1142,7 @@ void dump_mmu(CPUPPCState *env)
 }
 }
 
-int get_physical_address_wtlb(CPUPPCState *env, mmu_ctx_t *ctx,
+static int get_physical_address_wtlb(CPUPPCState *env, mmu_ctx_t *ctx,
  target_ulong eaddr,
  MMUAccessType access_type, int type,
  int mmu_idx)
@@ -1150,6 +1161,7 @@ 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)) {
+memset(ctx, 0, sizeof(*ctx));
 ctx->raddr = eaddr;
 ctx->prot = PAGE_RWX;
 return 0;
-- 
2.30.9




[PATCH v3 23/33] target/ppc/mmu_common.c: Remove BookE from direct store handling

2024-05-07 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 
---
 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 87cac12d68..03b834eb77 100644
--- a/target/ppc/mmu_common.c
+++ b/target/ppc/mmu_common.c
@@ -1287,12 +1287,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 v3 16/33] target/ppc/mmu_common.c: Simplify mmubooke_get_physical_address()

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

diff --git a/target/ppc/mmu_common.c b/target/ppc/mmu_common.c
index 7283eafe27..9793e6d282 100644
--- a/target/ppc/mmu_common.c
+++ b/target/ppc/mmu_common.c
@@ -652,31 +652,24 @@ static int mmubooke_get_physical_address(CPUPPCState 
*env, mmu_ctx_t *ctx,
  MMUAccessType access_type)
 {
 ppcemb_tlb_t *tlb;
-hwaddr raddr;
-int i, ret;
+hwaddr raddr = (hwaddr)-1ULL;
+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,
  access_type, i);
 if (ret != -1) {
+if (ret >= 0) {
+ctx->raddr = raddr;
+}
 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, raddr, ctx->prot, ret);
 return ret;
 }
 
-- 
2.30.9




[PATCH v3 15/33] target/ppc/mmu_common.c: Inline and remove check_physical()

2024-05-07 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 e03a433f02..7283eafe27 100644
--- a/target/ppc/mmu_common.c
+++ b/target/ppc/mmu_common.c
@@ -1148,28 +1148,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,
@@ -1189,7 +1167,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 v3 06/33] target/ppc/mmu_common.c: Remove unneeded local variable

2024-05-07 Thread BALATON Zoltan
In mmubooke_check_tlb() and mmubooke206_check_tlb() we can assign the
value directly the 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 v3 19/33] target/ppc/mmu_common.c: Deindent ppc_jumbo_xlate()

2024-05-07 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 3f584f2655..b1b2d64b90 100644
--- a/target/ppc/mmu_common.c
+++ b/target/ppc/mmu_common.c
@@ -1252,187 +1252,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 v3 18/33] target/ppc/mmu_common.c: Fix misindented qemu_log_mask() calls

2024-05-07 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 a5bc747f40..3f584f2655 100644
--- a/target/ppc/mmu_common.c
+++ b/target/ppc/mmu_common.c
@@ -318,8 +318,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];
@@ -333,9 +333,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 */
@@ -367,12 +367,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);
 }
 }
 }
@@ -418,9 +417,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) {
@@ -586,9 +584,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;
 }
@@ -700,11 +698,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 v3 09/33] target/ppc/mmu_common.c: Introduce mmu6xx_get_physical_address()

2024-05-07 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 
---
 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 aa137123a4..181273579b 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 v3 28/33] target/ppc/mmu_common.c: Move BookE MMU functions together

2024-05-07 Thread BALATON Zoltan
Signed-off-by: BALATON Zoltan 
---
 target/ppc/mmu_common.c | 226 
 1 file changed, 113 insertions(+), 113 deletions(-)

diff --git a/target/ppc/mmu_common.c b/target/ppc/mmu_common.c
index 04e5ad661d..a6e7b64049 100644
--- a/target/ppc/mmu_common.c
+++ b/target/ppc/mmu_common.c
@@ -854,6 +854,119 @@ found_tlb:
 return ret;
 }
 
+static void booke206_update_mas_tlb_miss(CPUPPCState *env, target_ulong 
address,
+ MMUAccessType access_type, int 
mmu_idx)
+{
+uint32_t epid;
+bool as, pr;
+uint32_t missed_tid = 0;
+bool use_epid = mmubooke206_get_as(env, mmu_idx, , , );
+
+if (access_type == MMU_INST_FETCH) {
+as = FIELD_EX64(env->msr, MSR, IR);
+}
+env->spr[SPR_BOOKE_MAS0] = env->spr[SPR_BOOKE_MAS4] & MAS4_TLBSELD_MASK;
+env->spr[SPR_BOOKE_MAS1] = env->spr[SPR_BOOKE_MAS4] & MAS4_TSIZED_MASK;
+env->spr[SPR_BOOKE_MAS2] = env->spr[SPR_BOOKE_MAS4] & MAS4_WIMGED_MASK;
+env->spr[SPR_BOOKE_MAS3] = 0;
+env->spr[SPR_BOOKE_MAS6] = 0;
+env->spr[SPR_BOOKE_MAS7] = 0;
+
+/* AS */
+if (as) {
+env->spr[SPR_BOOKE_MAS1] |= MAS1_TS;
+env->spr[SPR_BOOKE_MAS6] |= MAS6_SAS;
+}
+
+env->spr[SPR_BOOKE_MAS1] |= MAS1_VALID;
+env->spr[SPR_BOOKE_MAS2] |= address & MAS2_EPN_MASK;
+
+if (!use_epid) {
+switch (env->spr[SPR_BOOKE_MAS4] & MAS4_TIDSELD_PIDZ) {
+case MAS4_TIDSELD_PID0:
+missed_tid = env->spr[SPR_BOOKE_PID];
+break;
+case MAS4_TIDSELD_PID1:
+missed_tid = env->spr[SPR_BOOKE_PID1];
+break;
+case MAS4_TIDSELD_PID2:
+missed_tid = env->spr[SPR_BOOKE_PID2];
+break;
+}
+env->spr[SPR_BOOKE_MAS6] |= env->spr[SPR_BOOKE_PID] << 16;
+} else {
+missed_tid = epid;
+env->spr[SPR_BOOKE_MAS6] |= missed_tid << 16;
+}
+env->spr[SPR_BOOKE_MAS1] |= (missed_tid << MAS1_TID_SHIFT);
+
+
+/* next victim logic */
+env->spr[SPR_BOOKE_MAS0] |= env->last_way << MAS0_ESEL_SHIFT;
+env->last_way++;
+env->last_way &= booke206_tlb_ways(env, 0) - 1;
+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;
+mmu_ctx_t ctx;
+int 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 = ctx.raddr;
+*protp = ctx.prot;
+*psizep = TARGET_PAGE_BITS;
+return true;
+} else if (!guest_visible) {
+return false;
+}
+
+log_cpu_state_mask(CPU_LOG_MMU, cs, 0);
+env->error_code = 0;
+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);
+}
+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;
+case -3:
+/* No execute protection violation */
+if (access_type == MMU_INST_FETCH) {
+cs->exception_index = POWERPC_EXCP_ISI;
+env->spr[SPR_BOOKE_ESR] = 0;
+}
+break;
+}
+
+return false;
+}
+
 static const char *book3e_tsize_to_str[32] = {
 "1K", "2K", "4K", "8K", "16K", "32K", "64K", "128K", "256K", "512K",
 "1M", "2M", "4M", "8M", "16M", "32M", "64M", "128M", "256M", "512M",
@@ -1125,119 +1238,6 @@ static int get_physical_address_wtlb(CPUPPCState *env, 
mmu_ctx_t *ctx,
 }
 }
 
-static void booke206_update_mas_tlb_miss(CPUPPCState *env, target_ulong 
address,
- MMUAccessType access_type, int 
mmu_idx)
-{
-uint32_t epid;
-bool as, pr;
-uint32_t missed_tid = 0;
-bool use_epid = mmubooke206_get_as(env, mmu_idx, , , );
-
-if (access_type == MMU_INST_FETCH) {
-as = FIELD_EX64(env->msr, MSR, IR);
-}
-

[PATCH v3 14/33] target/ppc/mmu_common.c: Split off real mode cases in get_physical_address_wtlb()

2024-05-07 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 5a0df60ebc..e03a433f02 100644
--- a/target/ppc/mmu_common.c
+++ b/target/ppc/mmu_common.c
@@ -1175,7 +1175,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) {
@@ -1187,38 +1186,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 v3 22/33] target/ppc: Remove pp_check() and reuse ppc_hash32_pp_prot()

2024-05-07 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 in internal.h 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/internal.h   | 35 
 target/ppc/mmu-hash32.c | 45 -
 target/ppc/mmu_common.c | 44 ++--
 3 files changed, 37 insertions(+), 87 deletions(-)

diff --git a/target/ppc/internal.h b/target/ppc/internal.h
index 4a90dd2584..46176c4711 100644
--- a/target/ppc/internal.h
+++ b/target/ppc/internal.h
@@ -256,6 +256,41 @@ static inline int prot_for_access_type(MMUAccessType 
access_type)
 #ifndef CONFIG_USER_ONLY
 
 /* PowerPC MMU emulation */
+static inline 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:
+g_assert_not_reached();
+}
+} 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:
+g_assert_not_reached();
+}
+}
+return nx ? prot : prot | PAGE_EXEC;
+}
 
 bool ppc_xlate(PowerPCCPU *cpu, vaddr eaddr, MMUAccessType access_type,
   hwaddr *raddrp, int *psizep, int *protp,
diff --git a/target/ppc/mmu-hash32.c b/target/ppc/mmu-hash32.c
index 6dfedab11d..960751a50e 100644
--- a/target/ppc/mmu-hash32.c
+++ b/target/ppc/mmu-hash32.c
@@ -43,51 +43,6 @@ struct mmu_ctx_hash32 {
 int key;   /* Access key*/
 };
 
-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_common.c b/target/ppc/mmu_common.c
index d92c9607b8..87cac12d68 100644
--- a/target/ppc/mmu_common.c
+++ b/target/ppc/mmu_common.c
@@ -76,44 +76,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;
-}
-
 static int check_prot(int prot, MMUAccessType access_type)
 {
 return prot & prot_for_access_type(access_type) ? 0 : -2;
@@ -141,7 +103,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 */
@@ -160,11 +122,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);
 ret = 

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

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

Signed-off-by: BALATON Zoltan 
---
 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 v3 20/33] target/ppc/mmu_common.c: Replace hard coded constants in ppc_jumbo_xlate()

2024-05-07 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 b1b2d64b90..63b5fb98d1 100644
--- a/target/ppc/mmu_common.c
+++ b/target/ppc/mmu_common.c
@@ -1275,13 +1275,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 v3 24/33] target/ppc/mmu_common.c: Split off BookE handling from ppc_jumbo_xlate()

2024-05-07 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 
---
 target/ppc/mmu_common.c | 128 +---
 1 file changed, 92 insertions(+), 36 deletions(-)

diff --git a/target/ppc/mmu_common.c b/target/ppc/mmu_common.c
index 03b834eb77..83dc041a77 100644
--- a/target/ppc/mmu_common.c
+++ b/target/ppc/mmu_common.c
@@ -1194,6 +1194,92 @@ 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;
+mmu_ctx_t ctx;
+int 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 = ctx.raddr;
+*protp = ctx.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. */
 static bool ppc_jumbo_xlate(PowerPCCPU *cpu, vaddr eaddr,
@@ -1246,15 +1332,6 @@ 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_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;
 case POWERPC_MMU_REAL:
 cpu_abort(cs, "PowerPC in real mode should never raise "
   "any MMU exceptions\n");
@@ -1265,23 +1342,12 @@ static bool ppc_jumbo_xlate(PowerPCCPU *cpu, vaddr 
eaddr,
 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;
-   

[PATCH v3 26/33] target/ppc/mmu_common.c: Simplify ppc_booke_xlate() part 1

2024-05-07 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 
---
 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 788e2bebd5..c725a7932f 100644
--- a/target/ppc/mmu_common.c
+++ b/target/ppc/mmu_common.c
@@ -1205,58 +1205,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 v3 04/33] target/ppc: Remove unused helper

2024-05-07 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 v3 08/33] target/ppc/mmu_common.c: Drop cases for unimplemented MPC8xx MMU

2024-05-07 Thread BALATON Zoltan
The default case will catch this and abort the same way and there is
still a warning about it in ppc_tlb_invalidate_all() so drop these
from mmu_common.c to simplify this code.

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

diff --git a/target/ppc/mmu_common.c b/target/ppc/mmu_common.c
index 886fb6a657..aa137123a4 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 */
-- 
2.30.9




[PATCH v3 11/33] target/ppc/mmu_common.c: Move some debug logging

2024-05-07 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 
---
 target/ppc/mmu_common.c | 55 +++--
 1 file changed, 26 insertions(+), 29 deletions(-)

diff --git a/target/ppc/mmu_common.c b/target/ppc/mmu_common.c
index 9d337a73ba..b2f2cee1a8 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,37 @@ 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);
+PowerPCCPU *cpu = env_archcpu(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
 return ret;
 }
 
@@ -420,29 +440,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 v3 03/33] target/ppc: Simplify syscall exception handlers

2024-05-07 Thread BALATON Zoltan
After previous changes the hypercall handling in 7xx and 74xx
exception handlers can be folded into one if statement to simplify
this code. Also add "unlikely" to mark the less frequently used branch
for the compiler.

Signed-off-by: BALATON Zoltan 
Reviewed-by: Harsh Prateek Bora 
---
 target/ppc/excp_helper.c | 22 ++
 1 file changed, 6 insertions(+), 16 deletions(-)

diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c
index 5aa84bccd2..d19212f772 100644
--- a/target/ppc/excp_helper.c
+++ b/target/ppc/excp_helper.c
@@ -762,26 +762,21 @@ static void powerpc_excp_7xx(PowerPCCPU *cpu, int excp)
 case POWERPC_EXCP_SYSCALL:   /* System call exception*/
 {
 int lev = env->error_code;
-
-if (lev == 1 && cpu->vhyp) {
-dump_hcall(env);
-} else {
-dump_syscall(env);
-}
 /*
  * The Virtual Open Firmware (VOF) relies on the 'sc 1'
  * instruction to communicate with QEMU. The pegasos2 machine
  * uses VOF and the 7xx CPUs, so although the 7xx don't have
  * HV mode, we need to keep hypercall support.
  */
-if (lev == 1 && cpu->vhyp) {
+if (unlikely(lev == 1 && cpu->vhyp)) {
 PPCVirtualHypervisorClass *vhc =
 PPC_VIRTUAL_HYPERVISOR_GET_CLASS(cpu->vhyp);
+dump_hcall(env);
 vhc->hypercall(cpu->vhyp, cpu);
 powerpc_reset_excp_state(cpu);
 return;
 }
-
+dump_syscall(env);
 break;
 }
 case POWERPC_EXCP_FPU:   /* Floating-point unavailable exception */
@@ -907,26 +902,21 @@ static void powerpc_excp_74xx(PowerPCCPU *cpu, int excp)
 case POWERPC_EXCP_SYSCALL:   /* System call exception*/
 {
 int lev = env->error_code;
-
-if (lev == 1 && cpu->vhyp) {
-dump_hcall(env);
-} else {
-dump_syscall(env);
-}
 /*
  * The Virtual Open Firmware (VOF) relies on the 'sc 1'
  * instruction to communicate with QEMU. The pegasos2 machine
  * uses VOF and the 74xx CPUs, so although the 74xx don't have
  * HV mode, we need to keep hypercall support.
  */
-if (lev == 1 && cpu->vhyp) {
+if (unlikely(lev == 1 && cpu->vhyp)) {
 PPCVirtualHypervisorClass *vhc =
 PPC_VIRTUAL_HYPERVISOR_GET_CLASS(cpu->vhyp);
+dump_hcall(env);
 vhc->hypercall(cpu->vhyp, cpu);
 powerpc_reset_excp_state(cpu);
 return;
 }
-
+dump_syscall(env);
 break;
 }
 case POWERPC_EXCP_FPU:   /* Floating-point unavailable exception */
-- 
2.30.9




[PATCH v3 02/33] target/ppc: Move patching nip from exception handler to helper_scv

2024-05-07 Thread BALATON Zoltan
From: Nicholas Piggin 

Unlike sc, for scv a facility unavailable interrupt must be generated
if FSCR[SCV]=0 so we can't raise the exception with nip set to next
instruction but we can move advancing nip if the FSCR check passes to
helper_scv so the exception handler does not need to change it.

[balaton: added commit message]
Signed-off-by: BALATON Zoltan 
---
 target/ppc/excp_helper.c | 2 +-
 target/ppc/translate.c   | 6 +-
 2 files changed, 6 insertions(+), 2 deletions(-)

diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c
index 92fe535815..5aa84bccd2 100644
--- a/target/ppc/excp_helper.c
+++ b/target/ppc/excp_helper.c
@@ -1415,7 +1415,6 @@ static void powerpc_excp_books(PowerPCCPU *cpu, int excp)
 case POWERPC_EXCP_SYSCALL_VECTORED: /* scv exception */
 lev = env->error_code;
 dump_syscall(env);
-env->nip += 4;
 new_msr |= env->msr & ((target_ulong)1 << MSR_EE);
 new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
 
@@ -2524,6 +2523,7 @@ void helper_ppc_maybe_interrupt(CPUPPCState *env)
 void helper_scv(CPUPPCState *env, uint32_t lev)
 {
 if (env->spr[SPR_FSCR] & (1ull << FSCR_SCV)) {
+env->nip += 4;
 raise_exception_err(env, POWERPC_EXCP_SYSCALL_VECTORED, lev);
 } else {
 raise_exception_err(env, POWERPC_EXCP_FU, FSCR_IC_SCV);
diff --git a/target/ppc/translate.c b/target/ppc/translate.c
index e112c44a02..1d4e9f0679 100644
--- a/target/ppc/translate.c
+++ b/target/ppc/translate.c
@@ -4493,7 +4493,11 @@ static void gen_scv(DisasContext *ctx)
 {
 uint32_t lev = (ctx->opcode >> 5) & 0x7F;
 
-/* Set the PC back to the faulting instruction. */
+/*
+ * Set the PC back to the scv instruction (unlike sc), because a facility
+ * unavailable interrupt must be generated if FSCR[SCV]=0. The helper
+ * advances nip if the FSCR check passes.
+ */
 gen_update_nip(ctx, ctx->cia);
 gen_helper_scv(tcg_env, tcg_constant_i32(lev));
 
-- 
2.30.9




[PATCH v3 07/33] target/ppc/mmu_common.c: Simplify checking for real mode

2024-05-07 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 v3 01/33] target/ppc: Fix gen_sc to use correct nip

2024-05-07 Thread BALATON Zoltan
Most exceptions are raised with nip pointing to the faulting
instruction but the sc instruction generating a syscall exception
leaves nip pointing to next instruction. Fix gen_sc to not use
gen_exception_err() which sets nip back but correctly set nip to
pc_next so we don't have to patch this in the exception handlers.

Signed-off-by: BALATON Zoltan 
---
 target/ppc/excp_helper.c | 43 ++--
 target/ppc/translate.c   | 15 ++
 2 files changed, 8 insertions(+), 50 deletions(-)

diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c
index 0712098cf7..92fe535815 100644
--- a/target/ppc/excp_helper.c
+++ b/target/ppc/excp_helper.c
@@ -116,7 +116,7 @@ static void dump_syscall(CPUPPCState *env)
   ppc_dump_gpr(env, 0), ppc_dump_gpr(env, 3),
   ppc_dump_gpr(env, 4), ppc_dump_gpr(env, 5),
   ppc_dump_gpr(env, 6), ppc_dump_gpr(env, 7),
-  ppc_dump_gpr(env, 8), env->nip);
+  ppc_dump_gpr(env, 8), env->nip - 4);
 }
 
 static void dump_hcall(CPUPPCState *env)
@@ -131,7 +131,7 @@ static void dump_hcall(CPUPPCState *env)
   ppc_dump_gpr(env, 7), ppc_dump_gpr(env, 8),
   ppc_dump_gpr(env, 9), ppc_dump_gpr(env, 10),
   ppc_dump_gpr(env, 11), ppc_dump_gpr(env, 12),
-  env->nip);
+  env->nip - 4);
 }
 
 #ifdef CONFIG_TCG
@@ -516,12 +516,6 @@ static void powerpc_excp_40x(PowerPCCPU *cpu, int excp)
 break;
 case POWERPC_EXCP_SYSCALL:   /* System call exception*/
 dump_syscall(env);
-
-/*
- * We need to correct the NIP which in this case is supposed
- * to point to the next instruction
- */
-env->nip += 4;
 break;
 case POWERPC_EXCP_FIT:   /* Fixed-interval timer interrupt   */
 trace_ppc_excp_print("FIT");
@@ -632,12 +626,6 @@ static void powerpc_excp_6xx(PowerPCCPU *cpu, int excp)
 break;
 case POWERPC_EXCP_SYSCALL:   /* System call exception*/
 dump_syscall(env);
-
-/*
- * We need to correct the NIP which in this case is supposed
- * to point to the next instruction
- */
-env->nip += 4;
 break;
 case POWERPC_EXCP_FPU:   /* Floating-point unavailable exception */
 case POWERPC_EXCP_DECR:  /* Decrementer exception*/
@@ -780,13 +768,6 @@ static void powerpc_excp_7xx(PowerPCCPU *cpu, int excp)
 } else {
 dump_syscall(env);
 }
-
-/*
- * We need to correct the NIP which in this case is supposed
- * to point to the next instruction
- */
-env->nip += 4;
-
 /*
  * The Virtual Open Firmware (VOF) relies on the 'sc 1'
  * instruction to communicate with QEMU. The pegasos2 machine
@@ -932,13 +913,6 @@ static void powerpc_excp_74xx(PowerPCCPU *cpu, int excp)
 } else {
 dump_syscall(env);
 }
-
-/*
- * We need to correct the NIP which in this case is supposed
- * to point to the next instruction
- */
-env->nip += 4;
-
 /*
  * The Virtual Open Firmware (VOF) relies on the 'sc 1'
  * instruction to communicate with QEMU. The pegasos2 machine
@@ -1098,12 +1072,6 @@ static void powerpc_excp_booke(PowerPCCPU *cpu, int excp)
 break;
 case POWERPC_EXCP_SYSCALL:   /* System call exception*/
 dump_syscall(env);
-
-/*
- * We need to correct the NIP which in this case is supposed
- * to point to the next instruction
- */
-env->nip += 4;
 break;
 case POWERPC_EXCP_FPU:   /* Floating-point unavailable exception */
 case POWERPC_EXCP_APU:   /* Auxiliary processor unavailable  */
@@ -1428,13 +1396,6 @@ static void powerpc_excp_books(PowerPCCPU *cpu, int excp)
 } else {
 dump_syscall(env);
 }
-
-/*
- * We need to correct the NIP which in this case is supposed
- * to point to the next instruction
- */
-env->nip += 4;
-
 /* "PAPR mode" built-in hypercall emulation */
 if (lev == 1 && books_vhyp_handles_hcall(cpu)) {
 PPCVirtualHypervisorClass *vhc =
diff --git a/target/ppc/translate.c b/target/ppc/translate.c
index 93ffec787c..e112c44a02 100644
--- a/target/ppc/translate.c
+++ b/target/ppc/translate.c
@@ -4472,22 +4472,19 @@ static void gen_hrfid(DisasContext *ctx)
 #endif
 
 /* sc */
-#if defined(CONFIG_USER_ONLY)
-#define POWERPC_SYSCALL POWERPC_EXCP_SYSCALL_USER
-#else
-#define POWERPC_SYSCALL POWERPC_EXCP_SYSCALL
-#endif
 static void gen_sc(DisasContext *ctx)
 {
-uint32_t lev;
-
 /*
  * LEV is a 7-bit field, but the top 6 bits are treated as a reserved
  * field (i.e., ignored). ISA v3.1 changes that 

[PATCH v3 00/33] Misc PPC exception and BookE MMU clean ups

2024-05-07 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.

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


BALATON Zoltan (33):
  target/ppc: Fix gen_sc to use correct nip
  target/ppc: Move patching nip from exception handler to helper_scv
  target/ppc: Simplify syscall exception handlers
  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: Simplify mmubooke_get_physical_address()
  target/ppc/mmu_common.c: Simplify mmubooke206_get_physical_address()
  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: Make get_physical_address_wtlb() static
  target/ppc: Remove pp_check() and reuse ppc_hash32_pp_prot()
  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: Remove BookE handling from
get_physical_address_wtlb()
  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: Move BookE MMU functions together
  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 macro to check for page protection bit

 hw/ppc/pegasos2.c|   2 +-
 target/ppc/cpu.h |   1 -
 target/ppc/cpu_init.c|  69 ++-
 target/ppc/excp_helper.c |  67 +--
 target/ppc/helper.h  |   2 -
 target/ppc/helper_regs.c |   1 -
 target/ppc/internal.h|  72 +--
 target/ppc/mmu-hash32.c  |  54 +--
 target/ppc/mmu-hash64.c  |   2 +-
 target/ppc/mmu-radix64.c |   5 +-
 target/ppc/mmu_common.c  | 954 +--
 target/ppc/mmu_helper.c  |  36 +-
 target/ppc/translate.c   |  21 +-
 13 files changed, 517 insertions(+), 769 deletions(-)

-- 
2.30.9




[PATCH v3 05/33] target/ppc/mmu_common.c: Move calculation of a value closer to its usage

2024-05-07 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




RE: [PATCH] ui/gtk: Explicitly set the default size of new window when untabifying

2024-05-07 Thread Kim, Dongwon
Hi Marc-André,

I found that the problem is actually due to scaling factor of 0.25 
(VC_SCALE_MIN).

static void gd_update_geometry_hints(VirtualConsole *vc)
{
GtkDisplayState *s = vc->s;
GdkWindowHints mask = 0;
GdkGeometry geo = {};
GtkWidget *geo_widget = NULL;
GtkWindow *geo_window;

if (vc->type == GD_VC_GFX) {
if (!vc->gfx.ds) {
return;
}
if (s->free_scale) {
geo.min_width  = surface_width(vc->gfx.ds) * VC_SCALE_MIN;
geo.min_height = surface_height(vc->gfx.ds) * VC_SCALE_MIN;
mask |= GDK_HINT_MIN_SIZE;
} else {
geo.min_width  = surface_width(vc->gfx.ds) * vc->gfx.scale_x;
geo.min_height = surface_height(vc->gfx.ds) * vc->gfx.scale_y;
mask |= GDK_HINT_MIN_SIZE;
}
geo_widget = vc->gfx.drawing_area;
gtk_widget_set_size_request(geo_widget, geo.min_width, geo.min_height);

s->free_scale is set when 'zoom_to_fit' is set. This 'zoom_to_fit' is normally 
set via param but it is unconditionally set when
ui_info is supported like when some display device is enabled like virtio-vga.

So here free_scale is true so min_width and min_height are set to 1/4 of 
original width/height of the surface (640x480). That is totally fine.
But the real problem is at 

gtk_widget_set_size_request(geo_widget, geo.min_width, geo.min_height);

I do not understand why we are making set size request with these "min" values.

This commit from Gerd originally introduced the 0.25 scaling factor but not 
sure what is intention there.
(I hope Gerd can comment on this.)

commit 82fc18099aa8ee2533add523cc0069f26a83e7b6
Author: Gerd Hoffmann 
Date:   Fri May 16 12:26:12 2014 +0200

gtk: window sizing overhaul

Major overhaul for window size handling.  This basically switches qemu
over to use geometry hints for the window manager instead of trying to
get the job done with widget resize requests.  This allows to specify
better what we need and also avoids window resizes.

FIXME: on gtk2 someone overwrites the geometry hints :(

Signed-off-by: Gerd Hoffmann 

I am wondering if we could just set geo.base_width and height to the normal 
size then use these instead when making size request there.

Can you share your thought?

Thanks,
DW

> -Original Message-
> From: qemu-devel-bounces+dongwon.kim=intel@nongnu.org  devel-bounces+dongwon.kim=intel@nongnu.org> On Behalf Of Kim,
> Dongwon
> Sent: Tuesday, May 7, 2024 9:06 AM
> To: Marc-André Lureau 
> Cc: qemu-devel@nongnu.org; kra...@redhat.com
> Subject: RE: [PATCH] ui/gtk: Explicitly set the default size of new window 
> when
> untabifying
> 
> Hi Marc-André,
> 
> > -Original Message-
> > From: Marc-André Lureau 
> > Sent: Tuesday, May 7, 2024 8:10 AM
> > To: Kim, Dongwon 
> > Cc: qemu-devel@nongnu.org; kra...@redhat.com
> > Subject: Re: [PATCH] ui/gtk: Explicitly set the default size of new
> > window when untabifying
> >
> > Hi
> >
> > On Wed, May 1, 2024 at 7:47 AM  wrote:
> > >
> > > From: Dongwon Kim 
> > >
> > > When untabifying, the default size of the new window was
> > > inadvertently set to the size smaller than quarter of the primary
> > > window size due to lack of explicit configuration. This commit
> > > addresses the issue by ensuring that the size of untabified windows
> > > is set to match the surface size.
> >
> > From a quick test, I don't see a difference of behaviour after the
> > patch. Could you help me reproduce the issue?
> >
> > I also don't think it is correct for two reasons:
> > - the inner display widget should cause a window size reconfiguration
> > - the window size != display size
> 
> [Kim, Dongwon] Ok, I see this is happening only when virtio-vga device is used
> like
> qemu-system-x86_64 -m 2048 -enable-kvm -cpu host -smp cores=2 -drive
> file=./OVMF.fd,format=raw,if=pflash -device virtio-vga -display gtk,gl=on 
> Maybe
> some setting of dimensions is missing in there? I will take a look.
> 
> >
> > thanks
> >
> > > Cc: Gerd Hoffmann 
> > > Cc: Marc-André Lureau 
> > > Cc: Vivek Kasireddy 
> > > Signed-off-by: Dongwon Kim 
> > > ---
> > >  ui/gtk.c | 3 +++
> > >  1 file changed, 3 insertions(+)
> > >
> > > diff --git a/ui/gtk.c b/ui/gtk.c
> > > index 810d7fc796..269b8207d7 100644
> > > --- a/ui/gtk.c
> > > +++ b/ui/gtk.c
> > > @@ -1395,6 +1395,9 @@ static void gd_menu_untabify(GtkMenuItem
> > > *item,
> > void *opaque)
> > >  if (!vc->window) {
> > >  gtk_widget_set_sensitive(vc->menu_item, false);
> > >  vc->window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
> > > +gtk_window_set_default_size(GTK_WINDOW(vc->window),
> > > +surface_width(vc->gfx.ds),
> > > +surface_height(vc->gfx.ds));
> > >  #if defined(CONFIG_OPENGL)
> > >  if (vc->gfx.esurface) {
> > >  eglDestroySurface(qemu_egl_display, vc->gfx.esurface);
> > > --
> > > 2.34.1
> > 

Re: [PATCH v2 24/28] target/ppc/mmu_common.c: Remove BookE handling from get_physical_address_wtlb()

2024-05-07 Thread BALATON Zoltan

On Tue, 7 May 2024, Nicholas Piggin wrote:

On Thu May 2, 2024 at 9:43 AM AEST, BALATON Zoltan wrote:

This function is no longer called for BookE MMU model so remove parts
related to it. This has uncovered a few may be used uninitialised
warnings that are also fixed.

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

diff --git a/target/ppc/mmu_common.c b/target/ppc/mmu_common.c
index a1f98f8de4..d61c41d8c9 100644
--- a/target/ppc/mmu_common.c
+++ b/target/ppc/mmu_common.c
@@ -684,12 +684,10 @@ static int mmubooke_get_physical_address(CPUPPCState 
*env, mmu_ctx_t *ctx,
 ret = mmubooke_check_tlb(env, tlb, , >prot, address,
  access_type, i);
 if (ret != -1) {
-if (ret >= 0) {
-ctx->raddr = raddr;
-}
 break;
 }
 }
+ctx->raddr = raddr;
 qemu_log_mask(CPU_LOG_MMU,
   "%s: access %s " TARGET_FMT_lx " => " HWADDR_FMT_plx
   " %d %d\n", __func__, ret < 0 ? "refused" : "granted",
@@ -897,9 +895,6 @@ static int mmubooke206_get_physical_address(CPUPPCState 
*env, mmu_ctx_t *ctx,
 ret = mmubooke206_check_tlb(env, tlb, , >prot, address,
 access_type, mmu_idx);
 if (ret != -1) {
-if (ret >= 0) {
-ctx->raddr = raddr;
-}
 goto found_tlb;
 }
 }
@@ -907,6 +902,7 @@ static int mmubooke206_get_physical_address(CPUPPCState 
*env, mmu_ctx_t *ctx,

 found_tlb:

+ctx->raddr = raddr;


Not sure about the uninitialized warnings here either, caller probably
should not be using ctx->raddr unless we returned 0...


 qemu_log_mask(CPU_LOG_MMU, "%s: access %s " TARGET_FMT_lx " => "
   HWADDR_FMT_plx " %d %d\n", __func__,
   ret < 0 ? "refused" : "granted", address, raddr,
@@ -1163,20 +1159,9 @@ static 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, ctx, eaddr, access_type);
-} else if (env->mmu_model == POWERPC_MMU_BOOKE206) {
-return mmubooke206_get_physical_address(env, ctx, eaddr, access_type,
-mmu_idx);
-}


This could just go in the previous patch when you split booke xlate?


Removing this uncovers the warnings so I keep it here to separate it from 
the previous change. I gave up on trying to resolve these warnings and 
untangle the embedded functions from mmu_ctx_t which would be needed to 
move these booke functions out from this file. The other problem is that 
these booke get_physical_address functions and mmu40x_get_physical_address 
all use ppcemb_tlb_check which then needs to be in the same file and 
static to be inlined and not run too slow but 40x is still in jumbo_xlate 
so I just leave it for now and may return to it later or let somebody else 
continue from here. I think this series moves forward enough for now and I 
don't have more time now.



-
-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) {
 memset(ctx, 0, sizeof(*ctx));
 ctx->raddr = eaddr;
 ctx->prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;


This still changes beahviour of MPC8xx MMU doesn't it? It's supposed
to abort always.


I don't think it can get here because there's still an abort case in 
ppc_tlb_invalidate_all() which is called from ppc_cpu_reset_hold() so it 
will likely crash before it could call anything here. But if you think 
it's necessary I could add a case for it in ppc_xlate() maybe.


Regards,
BALATON Zoltan



RE: [PATCH v6] Hexagon: add PC alignment check and exception

2024-05-07 Thread Brian Cain



> -Original Message-
> From: Matheus Bernardino (QUIC) 
> Sent: Friday, May 3, 2024 11:53 AM
> To: qemu-devel@nongnu.org
> Cc: Brian Cain ; Sid Manning ;
> a...@rev.ng; a...@rev.ng; ltaylorsimp...@gmail.com;
> richard.hender...@linaro.org; Laurent Vivier 
> Subject: [PATCH v6] Hexagon: add PC alignment check and exception
> 
> The Hexagon Programmer's Reference Manual says that the exception 0x1e
> should be raised upon an unaligned program counter. Let's implement that
> and also add some tests.
> 
> Signed-off-by: Matheus Tavares Bernardino 
> Reviewed-by: Richard Henderson 
> Reviewed-by: Taylor Simpson 
> ---
> Changes in v6:
> - The multi COF test defines a new section for the unaligned label to
>   make it more robust.
> - Instead of a nop in the undesired test branch, we use a trap for
>   SYS_EXIT
> 

Reviewed-by: Brian Cain 

>  target/hexagon/cpu.h  |   7 ++
>  target/hexagon/cpu_bits.h |   4 ++
>  target/hexagon/macros.h   |   3 -
>  linux-user/hexagon/cpu_loop.c |   4 ++
>  target/hexagon/op_helper.c|   9 ++-
>  tests/tcg/hexagon/unaligned_pc.c  | 107 ++
>  tests/tcg/hexagon/Makefile.target |   2 +
>  7 files changed, 128 insertions(+), 8 deletions(-)
>  create mode 100644 tests/tcg/hexagon/unaligned_pc.c
> 
> diff --git a/target/hexagon/cpu.h b/target/hexagon/cpu.h
> index 3eef58fe8f..764f3c38cc 100644
> --- a/target/hexagon/cpu.h
> +++ b/target/hexagon/cpu.h
> @@ -134,6 +134,10 @@ struct ArchCPU {
> 
>  FIELD(TB_FLAGS, IS_TIGHT_LOOP, 0, 1)
> 
> +G_NORETURN void hexagon_raise_exception_err(CPUHexagonState *env,
> +uint32_t exception,
> +uintptr_t pc);
> +
>  static inline void cpu_get_tb_cpu_state(CPUHexagonState *env, vaddr *pc,
>  uint64_t *cs_base, uint32_t *flags)
>  {
> @@ -144,6 +148,9 @@ static inline void
> cpu_get_tb_cpu_state(CPUHexagonState *env, vaddr *pc,
>  hex_flags = FIELD_DP32(hex_flags, TB_FLAGS, IS_TIGHT_LOOP, 1);
>  }
>  *flags = hex_flags;
> +if (*pc & PCALIGN_MASK) {
> +hexagon_raise_exception_err(env, HEX_EXCP_PC_NOT_ALIGNED, 0);
> +}
>  }
> 
>  typedef HexagonCPU ArchCPU;
> diff --git a/target/hexagon/cpu_bits.h b/target/hexagon/cpu_bits.h
> index 96fef71729..4279281a71 100644
> --- a/target/hexagon/cpu_bits.h
> +++ b/target/hexagon/cpu_bits.h
> @@ -20,9 +20,13 @@
> 
>  #include "qemu/bitops.h"
> 
> +#define PCALIGN 4
> +#define PCALIGN_MASK (PCALIGN - 1)
> +
>  #define HEX_EXCP_FETCH_NO_UPAGE  0x012
>  #define HEX_EXCP_INVALID_PACKET  0x015
>  #define HEX_EXCP_INVALID_OPCODE  0x015
> +#define HEX_EXCP_PC_NOT_ALIGNED  0x01e
>  #define HEX_EXCP_PRIV_NO_UREAD   0x024
>  #define HEX_EXCP_PRIV_NO_UWRITE  0x025
> 
> diff --git a/target/hexagon/macros.h b/target/hexagon/macros.h
> index 1376d6ccc1..f375471a98 100644
> --- a/target/hexagon/macros.h
> +++ b/target/hexagon/macros.h
> @@ -22,9 +22,6 @@
>  #include "hex_regs.h"
>  #include "reg_fields.h"
> 
> -#define PCALIGN 4
> -#define PCALIGN_MASK (PCALIGN - 1)
> -
>  #define GET_FIELD(FIELD, REGIN) \
>  fEXTRACTU_BITS(REGIN, reg_field_info[FIELD].width, \
> reg_field_info[FIELD].offset)
> diff --git a/linux-user/hexagon/cpu_loop.c b/linux-user/hexagon/cpu_loop.c
> index 7f1499ed28..d41159e52a 100644
> --- a/linux-user/hexagon/cpu_loop.c
> +++ b/linux-user/hexagon/cpu_loop.c
> @@ -60,6 +60,10 @@ void cpu_loop(CPUHexagonState *env)
>  env->gpr[0] = ret;
>  }
>  break;
> +case HEX_EXCP_PC_NOT_ALIGNED:
> +force_sig_fault(TARGET_SIGBUS, TARGET_BUS_ADRALN,
> +env->gpr[HEX_REG_R31]);
> +break;
>  case EXCP_ATOMIC:
>  cpu_exec_step_atomic(cs);
>  break;
> diff --git a/target/hexagon/op_helper.c b/target/hexagon/op_helper.c
> index da10ac5847..ae5a605513 100644
> --- a/target/hexagon/op_helper.c
> +++ b/target/hexagon/op_helper.c
> @@ -36,10 +36,9 @@
>  #define SF_MANTBITS23
> 
>  /* Exceptions processing helpers */
> -static G_NORETURN
> -void do_raise_exception_err(CPUHexagonState *env,
> -uint32_t exception,
> -uintptr_t pc)
> +G_NORETURN void hexagon_raise_exception_err(CPUHexagonState *env,
> +uint32_t exception,
> +uintptr_t pc)
>  {
>  CPUState *cs = env_cpu(env);
>  qemu_log_mask(CPU_LOG_INT, "%s: %d\n", __func__, exception);
> @@ -49,7 +48,7 @@ void do_raise_exception_err(CPUHexagonState *env,
> 
>  G_NORETURN void HELPER(raise_exception)(CPUHexagonState *env, uint32_t
> excp)
>  {
> -do_raise_exception_err(env, excp, 0);
> +hexagon_raise_exception_err(env, excp, 0);
>  }
> 
>  void log_store32(CPUHexagonState *env, target_ulong addr,
> diff --git 

Re: [PATCH v4 0/2] query-cpu-model-expansion: report deprecated features

2024-05-07 Thread Collin Walling
[...]

Thanks everyone!  The RFC for the analogous libvirt patches have been
posted under the subject:

[RFC PATCH 0/1] support deprecated-props from query-cpu-model-expansion

Any and all feedback is welcome.

-- 
Regards,
  Collin




How unsubscribe

2024-05-07 Thread Jean-Christophe
Hello,How unsubscribe ?Dear 

Re: [PATCH V1 08/26] migration: vmstate_info_void_ptr

2024-05-07 Thread Fabiano Rosas
Steve Sistare  writes:

> Define VMSTATE_VOID_PTR so the value of a pointer (but not its target)
> can be saved in the migration stream.  This will be needed for CPR.
>
> Signed-off-by: Steve Sistare 

Reviewed-by: Fabiano Rosas 



Re: [PATCH 0/4] Fix "virtio-gpu: fix scanout migration post-load"

2024-05-07 Thread Peter Xu
On Tue, May 07, 2024 at 05:46:36PM -0300, Fabiano Rosas wrote:
> marcandre.lur...@redhat.com writes:
> 
> > From: Marc-André Lureau 
> >
> > Hi,
> >
> > The aforementioned patch breaks virtio-gpu device migrations for versions
> > pre-9.0/9.0, both forwards and backwards. Versioning of `VMS_STRUCT` is more
> > complex than it may initially appear, as evidenced in the problematic commit
> > dfcf74fa68c ("virtio-gpu: fix scanout migration post-load").
> >
> > To resolve this, we need to propagate the `vmstate` `version_id` through the
> > nested structures. Additionally, we should tie specific machine version to a
> > corresponding `version_id` to maintain migration compatibility.
> >
> > `VMS_VSTRUCT` allows specifying the appropriate version of the nested 
> > structure
> > to use.
> 
> This would have been caught by the migration-compat-x86_64 CI job had we
> added the virtio-gpu device to it.

I had exactly the same thoughts, and actually I added a todo after I
noticed this issue but I forgot to discuss with you today.. actually I have
one more on whether we can allow vmsd versioning to work for bi-direction
(then we can get rid of machine type dependencies), we may need the
handshake work as pre-requisite, so that two qemus need to talk first on
verify the vmsds.  But let's leave that for later.

> 
> $ cd build-8.2
> $ QTEST_TRACE='vmstate_*' QTEST_DEVICE_OPTS='-device virtio-gpu' \
> QTEST_QEMU_BINARY=./qemu-system-x86_64 \
> QTEST_QEMU_BINARY_DST=../build-9.0/qemu-system-x86_64 
> ./tests/qtest/migration-test
> ...
> vmstate_n_elems fb.offset: 1
> vmstate_subsection_load virtio-gpu-one-scanout
> vmstate_subsection_load_good virtio-gpu-one-scanout
> vmstate_load_state_end virtio-gpu-one-scanout end/0
> vmstate_subsection_load virtio-gpu-scanouts
> vmstate_subsection_load_good virtio-gpu-scanouts
> vmstate_load_state_end virtio-gpu-scanouts end/0
> vmstate_subsection_load virtio-gpu
> vmstate_subsection_load_good virtio-gpu
> vmstate_load_state_end virtio-gpu end/0
> vmstate_downtime_load type=non-iterable idstr=:00:03.0/virtio-gpu 
> instance_id=0 downtime=32118
> qemu-system-x86_64: Missing section footer for :00:03.0/virtio-gpu
> vmstate_downtime_checkpoint dst-precopy-loadvm-completed
> qemu-system-x86_64: load of migration failed: Invalid argument
> 
> Some considerations:
> 
> 1) Here QTEST_DEVICE_OPTS is a hack I added on top, it doesn't currently
>exist.
> 
> 2) This only uncovers relatively simple bugs where we don't need the
>guest to access the device, it just needs to be there.

Right, but having something to cover the basics would still be nice,
because the rarer the bug the less impact to users too (I hope!), so they
can be with lower priority too when tested.

> 
> We could take the steps to enable this kind of testing if we think it's
> worthwhile. Some downsides are:
> 
> a) the item (2) above - situations that depend on guest behavior are out
>of the picture because migration-test runs only a custom program that
>dirties memory;
> 
> b) this test only works in CI or in a pre setup environment because it
>needs the previous QEMU version to be built beforehand;
> 
> c) the full set of migration tests already runs a few times in CI via
>make check, plus the compat job. We'll probably need to do some
>simplification to avoid taking too much additional time;
> 
> d) there's also the obvious maintenance burden of choosing devices and
>doing the eventual upkeep of the QEMU command line for the
>migration-test.

The last one should be mostly fine, iiuc - we shouldn't add any device that
can easily break ABI, and the list of devices can start with a minumum; an
extreme case is we add one device only if something broke first with a
stable ABI.

Then if the ABI is stable, we need to go through the deprecation procedure,
and that takes two releases.  We can drop the device in migration-test in
the release of when deprecation starts.

Thanks,

-- 
Peter Xu




RE: [PATCH 3/4] target/hexagon: idef-parser fix leak of init_list

2024-05-07 Thread ltaylorsimpson



> -Original Message-
> From: 'Anton Johansson' 
> Sent: Tuesday, May 7, 2024 4:47 AM
> To: ltaylorsimp...@gmail.com
> Cc: qemu-devel@nongnu.org; a...@rev.ng; bc...@quicinc.com
> Subject: Re: [PATCH 3/4] target/hexagon: idef-parser fix leak of init_list
> 
> On 06/05/24, ltaylorsimp...@gmail.com wrote:
> >
> >
> > > -Original Message-
> > > From: Anton Johansson 
> > > Sent: Monday, May 6, 2024 1:31 PM
> > > To: qemu-devel@nongnu.org
> > > Cc: a...@rev.ng; ltaylorsimp...@gmail.com; bc...@quicinc.com
> > > Subject: [PATCH 3/4] target/hexagon: idef-parser fix leak of
> > > init_list
> > >
> > > gen_inst_init_args() is called for instructions using a predicate as
> > > an
> > rvalue.
> > > Upon first call, the list of arguments which might need
> > > initialization
> > init_list is
> > > freed to indicate that they have been processed. For instructions
> > > without
> > an
> > > rvalue predicate,
> > > gen_inst_init_args() isn't called and init_list will never be freed.
> > >
> > > Free init_list from free_instruction() if it hasn't already been freed.
> > >
> > > Signed-off-by: Anton Johansson 
> > > ---
> > >  target/hexagon/idef-parser/parser-helpers.c | 7 +++
> > >  1 file changed, 7 insertions(+)
> > >
> > > diff --git a/target/hexagon/idef-parser/parser-helpers.c
> > > b/target/hexagon/idef-parser/parser-helpers.c
> > > index 95f2b43076..bae01c2bb8 100644
> > > --- a/target/hexagon/idef-parser/parser-helpers.c
> > > +++ b/target/hexagon/idef-parser/parser-helpers.c
> > > @@ -2121,6 +2121,13 @@ void free_instruction(Context *c)
> > >  g_string_free(g_array_index(c->inst.strings, GString*, i), TRUE);
> > >  }
> > >  g_array_free(c->inst.strings, TRUE);
> > > +/*
> > > + * Free list of arguments that might need initialization, if
> > > + they
> > haven't
> > > + * already been free'd.
> > > + */
> > > +if (c->inst.init_list) {
> > > +g_array_free(c->inst.init_list, TRUE);
> > > +}
> > >  /* Free INAME token value */
> > >  g_string_free(c->inst.name, TRUE);
> > >  /* Free variables and registers */
> >
> > Why not do this in gen_inst_init_args just before this?
> >/* Free argument init list once we have initialized everything */
> > g_array_free(c->inst.init_list, TRUE);
> > c->inst.init_list = NULL;
> 
> Thanks for the reviews Taylor! I'm not sure I understand what you mean
> here, we already free init_list in gen_inst_init_args, since 
> gen_inst_init_args
> won't be called for all instructions we need to also free from a common
> place.
> 
> //Anton

It just seems more natural to free the elements of the array at the same place 
you free the array itself.  If there are valid reasons for doing it elsewhere, 
I'm OK with that.

Taylor





Re: [PATCH V1 07/26] migration: VMStateId

2024-05-07 Thread Fabiano Rosas
Steve Sistare  writes:

> Define a type for the 256 byte id string to guarantee the same length is
> used and enforced everywhere.
>
> Signed-off-by: Steve Sistare 

Reviewed-by: Fabiano Rosas 



Re: [PATCH V1 05/26] migration: precreate vmstate

2024-05-07 Thread Fabiano Rosas
Steve Sistare  writes:

> Provide the VMStateDescription precreate field to mark objects that must
> be loaded on the incoming side before devices have been created, because
> they provide properties that will be needed at creation time.  They will
> be saved to and loaded from their own QEMUFile, via

It's not obvious to me what the reason is to have a separate
QEMUFile. Could you expand on this?

> qemu_savevm_precreate_save and qemu_savevm_precreate_load, but these
> functions are not yet called in this patch.  Allow them to be called
> before or after normal migration is active, when current_migration and
> current_incoming are not valid.
>



Re: [PATCH 4/4] virtio-gpu: add x-vmstate-version

2024-05-07 Thread Fabiano Rosas
marcandre.lur...@redhat.com writes:

> From: Marc-André Lureau 
>
> Machine <= 8.2 use v1.
>
> Signed-off-by: Marc-André Lureau 

Reviewed-by: Fabiano Rosas 



Re: [PATCH v2 3/4] hw/nvme: Support SR-IOV VFs more than 127

2024-05-07 Thread Minwoo Im
On 24-05-01 14:46:39, Klaus Jensen wrote:
> On Apr  1 04:30, Minwoo Im wrote:
> > From: Minwoo Im 
> > 
> > The number of virtual functions(VFs) supported in SR-IOV is 64k as per
> > spec.  To test a large number of MSI-X vectors mapping to CPU matrix in
> > the QEMU system, we need much more than 127 VFs.  This patch made
> > support for 256 VFs per a physical function(PF).
> > 
> 
> With patch 2 in place, shouldn't it be relatively straight forward to
> convert the static array to be dynamic and just use numvfs to size it?
> Then we won't have to add another patch when someone comes around and
> wants to bump this again ;)

Sorry for the late response here.  I will update the 3rd patch to
convert secondary controller list static array to a dynamic array with
making the max_vfs parameter to uint32.



Re: [PATCH 0/4] Fix "virtio-gpu: fix scanout migration post-load"

2024-05-07 Thread Fabiano Rosas
marcandre.lur...@redhat.com writes:

> From: Marc-André Lureau 
>
> Hi,
>
> The aforementioned patch breaks virtio-gpu device migrations for versions
> pre-9.0/9.0, both forwards and backwards. Versioning of `VMS_STRUCT` is more
> complex than it may initially appear, as evidenced in the problematic commit
> dfcf74fa68c ("virtio-gpu: fix scanout migration post-load").
>
> To resolve this, we need to propagate the `vmstate` `version_id` through the
> nested structures. Additionally, we should tie specific machine version to a
> corresponding `version_id` to maintain migration compatibility.
>
> `VMS_VSTRUCT` allows specifying the appropriate version of the nested 
> structure
> to use.

This would have been caught by the migration-compat-x86_64 CI job had we
added the virtio-gpu device to it.

$ cd build-8.2
$ QTEST_TRACE='vmstate_*' QTEST_DEVICE_OPTS='-device virtio-gpu' \
QTEST_QEMU_BINARY=./qemu-system-x86_64 \
QTEST_QEMU_BINARY_DST=../build-9.0/qemu-system-x86_64 
./tests/qtest/migration-test
...
vmstate_n_elems fb.offset: 1
vmstate_subsection_load virtio-gpu-one-scanout
vmstate_subsection_load_good virtio-gpu-one-scanout
vmstate_load_state_end virtio-gpu-one-scanout end/0
vmstate_subsection_load virtio-gpu-scanouts
vmstate_subsection_load_good virtio-gpu-scanouts
vmstate_load_state_end virtio-gpu-scanouts end/0
vmstate_subsection_load virtio-gpu
vmstate_subsection_load_good virtio-gpu
vmstate_load_state_end virtio-gpu end/0
vmstate_downtime_load type=non-iterable idstr=:00:03.0/virtio-gpu 
instance_id=0 downtime=32118
qemu-system-x86_64: Missing section footer for :00:03.0/virtio-gpu
vmstate_downtime_checkpoint dst-precopy-loadvm-completed
qemu-system-x86_64: load of migration failed: Invalid argument

Some considerations:

1) Here QTEST_DEVICE_OPTS is a hack I added on top, it doesn't currently
   exist.

2) This only uncovers relatively simple bugs where we don't need the
   guest to access the device, it just needs to be there.

We could take the steps to enable this kind of testing if we think it's
worthwhile. Some downsides are:

a) the item (2) above - situations that depend on guest behavior are out
   of the picture because migration-test runs only a custom program that
   dirties memory;

b) this test only works in CI or in a pre setup environment because it
   needs the previous QEMU version to be built beforehand;

c) the full set of migration tests already runs a few times in CI via
   make check, plus the compat job. We'll probably need to do some
   simplification to avoid taking too much additional time;

d) there's also the obvious maintenance burden of choosing devices and
   doing the eventual upkeep of the QEMU command line for the
   migration-test.



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

2024-05-07 Thread Cord Amfmgm
On Wed, Apr 24, 2024 at 3:43 PM Cord Amfmgm  wrote:

> On Thu, Apr 18, 2024 at 10:43 AM Michael Tokarev  wrote:
>
>> 06.02.2024 10:13, Cord Amfmgm wrote:
>> > This changes the ohci validation to not assert if invalid
>> > data is fed to the ohci controller. The poc suggested in
>> > https://bugs.launchpad.net/qemu/+bug/1907042
>> > and then migrated to bug #303 does the following to
>> > feed it a SETUP pid and EndPt of 1:
>> >
>> >  uint32_t MaxPacket = 64;
>> >  uint32_t TDFormat = 0;
>> >  uint32_t Skip = 0;
>> >  uint32_t Speed = 0;
>> >  uint32_t Direction = 0;  /* #define OHCI_TD_DIR_SETUP 0 */
>> >  uint32_t EndPt = 1;
>> >  uint32_t FuncAddress = 0;
>> >  ed->attr = (MaxPacket << 16) | (TDFormat << 15) | (Skip << 14)
>> > | (Speed << 13) | (Direction << 11) | (EndPt << 7)
>> > | FuncAddress;
>> >  ed->tailp = /*TDQTailPntr= */ 0;
>> >  ed->headp = ((/*TDQHeadPntr= */ [0]) & 0xfff0)
>> > | (/* ToggleCarry= */ 0 << 1);
>> >  ed->next_ed = (/* NextED= */ 0 & 0xfff0)
>> >
>> > qemu-fuzz also caught the same issue in #1510. They are
>> > both fixed by this patch.
>> >
>> > The if (td.cbp > td.be) logic in ohci_service_td() causes an
>> > ohci_die(). My understanding of the OHCI spec 4.3.1.2
>> > Table 4-2 allows td.cbp to be one byte more than td.be to
>> > signal the buffer has zero length. The new check in qemu
>> > appears to have been added since qemu-4.2. This patch
>> > includes both fixes since they are located very close
>> > together.
>> >
>> > Signed-off-by: David Hubbard 
>>
>> Wonder if this got lost somehow.  Or is it not needed?
>>
>> Thanks,
>>
>> /mjt
>>
>
> Friendly ping! Gerd, can you chime in with how you would like to approach
> this? I still need this patch to unblock my qemu workflow - custom OS
> development.
>
>

Can I please ask for an update on this? I'm attempting to figure out if
this patch has been rejected and I need to resubmit / rework it at HEAD?


>
>> > diff --git a/hw/usb/hcd-ohci.c b/hw/usb/hcd-ohci.c
>> > index d73b53f33c..a53808126f 100644
>> > --- a/hw/usb/hcd-ohci.c
>> > +++ b/hw/usb/hcd-ohci.c
>> > @@ -927,6 +927,11 @@ static int ohci_service_td(OHCIState *ohci,
>> > struct ohci_ed *ed)
>> >   case OHCI_TD_DIR_SETUP:
>> >   str = "setup";
>> >   pid = USB_TOKEN_SETUP;
>> > +if (OHCI_BM(ed->flags, ED_EN) > 0) {  /* setup only allowed to
>> ep 0 */
>> > +trace_usb_ohci_td_bad_pid(str, ed->flags, td.flags);
>> > +ohci_die(ohci);
>> > +return 1;
>> > +}
>> >   break;
>> >   default:
>> >   trace_usb_ohci_td_bad_direction(dir);
>> > @@ -936,8 +941,8 @@ static int ohci_service_td(OHCIState *ohci, struct
>> > ohci_ed *ed)
>> >   if ((td.cbp & 0xf000) != (td.be & 0xf000)) {
>> >   len = (td.be & 0xfff) + 0x1001 - (td.cbp & 0xfff);
>> >   } else {
>> > -if (td.cbp > td.be) {
>> > -trace_usb_ohci_iso_td_bad_cc_overrun(td.cbp, td.be);
>> > +if (td.cbp > td.be + 1) {
>> > +trace_usb_ohci_td_bad_buf(td.cbp, td.be);
>> >   ohci_die(ohci);
>> >   return 1;
>> >   }
>> > diff --git a/hw/usb/trace-events b/hw/usb/trace-events
>> > index ed7dc210d3..b47d082fa3 100644
>> > --- a/hw/usb/trace-events
>> > +++ b/hw/usb/trace-events
>> > @@ -28,6 +28,8 @@ usb_ohci_iso_td_data_overrun(int ret, ssize_t len)
>> > "DataOverrun %d > %zu"
>> >   usb_ohci_iso_td_data_underrun(int ret) "DataUnderrun %d"
>> >   usb_ohci_iso_td_nak(int ret) "got NAK/STALL %d"
>> >   usb_ohci_iso_td_bad_response(int ret) "Bad device response %d"
>> > +usb_ohci_td_bad_buf(uint32_t cbp, uint32_t be) "Bad cbp = 0x%x > be =
>> 0x%x"
>> > +usb_ohci_td_bad_pid(const char *s, uint32_t edf, uint32_t tdf) "Bad
>> > pid %s: ed.flags 0x%x td.flags 0x%x"
>> >   usb_ohci_port_attach(int index) "port #%d"
>> >   usb_ohci_port_detach(int index) "port #%d"
>> >   usb_ohci_port_wakeup(int index) "port #%d"
>> >
>>
>


Re: [PATCH v10 0/7] Support message-based DMA in vfio-user server

2024-05-07 Thread Peter Xu
On Tue, May 07, 2024 at 07:34:24AM -0700, Mattias Nissler wrote:
> This series adds basic support for message-based DMA in qemu's vfio-user
> server. This is useful for cases where the client does not provide file
> descriptors for accessing system memory via memory mappings. My motivating use
> case is to hook up device models as PCIe endpoints to a hardware design. This
> works by bridging the PCIe transaction layer to vfio-user, and the endpoint
> does not access memory directly, but sends memory requests TLPs to the 
> hardware
> design in order to perform DMA.
> 
> Note that more work is needed to make message-based DMA work well: qemu
> currently breaks down DMA accesses into chunks of size 8 bytes at maximum, 
> each
> of which will be handled in a separate vfio-user DMA request message. This is
> quite terrible for large DMA accesses, such as when nvme reads and writes
> page-sized blocks for example. Thus, I would like to improve qemu to be able 
> to
> perform larger accesses, at least for indirect memory regions. I have 
> something
> working locally, but since this will likely result in more involved surgery 
> and
> discussion, I am leaving this to be addressed in a separate patch.

I assume Jag will pick this up then.

Thanks,

-- 
Peter Xu




Re: [PATCH v10 1/7] system/physmem: Replace qemu_mutex_lock() calls with QEMU_LOCK_GUARD

2024-05-07 Thread Peter Xu
On Tue, May 07, 2024 at 07:34:25AM -0700, Mattias Nissler wrote:
> From: Philippe Mathieu-Daudé 
> 
> From: Philippe Mathieu-Daudé 
> 
> Simplify cpu_[un]register_map_client() and cpu_notify_map_clients()
> by replacing the pair of qemu_mutex_lock/qemu_mutex_unlock calls by
> the WITH_QEMU_LOCK_GUARD() macro.
> 
> Signed-off-by: Philippe Mathieu-Daudé 
> Signed-off-by: Mattias Nissler 
> Reviewed-by: Mattias Nissler 

Reviewed-by: Peter Xu 

-- 
Peter Xu




Re: [PATCH v10 4/7] softmmu: Support concurrent bounce buffers

2024-05-07 Thread Peter Xu
On Tue, May 07, 2024 at 07:34:28AM -0700, Mattias Nissler wrote:
> When DMA memory can't be directly accessed, as is the case when
> running the device model in a separate process without shareable DMA
> file descriptors, bounce buffering is used.
> 
> It is not uncommon for device models to request mapping of several DMA
> regions at the same time. Examples include:
>  * net devices, e.g. when transmitting a packet that is split across
>several TX descriptors (observed with igb)
>  * USB host controllers, when handling a packet with multiple data TRBs
>(observed with xhci)
> 
> Previously, qemu only provided a single bounce buffer per AddressSpace
> and would fail DMA map requests while the buffer was already in use. In
> turn, this would cause DMA failures that ultimately manifest as hardware
> errors from the guest perspective.
> 
> This change allocates DMA bounce buffers dynamically instead of
> supporting only a single buffer. Thus, multiple DMA mappings work
> correctly also when RAM can't be mmap()-ed.
> 
> The total bounce buffer allocation size is limited individually for each
> AddressSpace. The default limit is 4096 bytes, matching the previous
> maximum buffer size. A new x-max-bounce-buffer-size parameter is
> provided to configure the limit for PCI devices.
> 
> Signed-off-by: Mattias Nissler 

Acked-by: Peter Xu 

-- 
Peter Xu




Re: [PATCH 3/4] virtio-gpu: use a VMState variant for the scanout field

2024-05-07 Thread Peter Xu
On Tue, May 07, 2024 at 03:19:19PM +0400, marcandre.lur...@redhat.com wrote:
> From: Marc-André Lureau 
> 
> Depending on the version, use v1 or v2 of the scanout VM state.
> 
> Signed-off-by: Marc-André Lureau 
> ---
>  hw/display/virtio-gpu.c | 22 +-
>  1 file changed, 17 insertions(+), 5 deletions(-)
> 
> diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c
> index ae831b6b3e..4fd72caf3f 100644
> --- a/hw/display/virtio-gpu.c
> +++ b/hw/display/virtio-gpu.c
> @@ -1191,17 +1191,29 @@ static const VMStateDescription 
> vmstate_virtio_gpu_scanout = {
>  },
>  };
>  
> +static bool vmstate_before_v2(void *opaque, int version)
> +{
> +return version <= 1;
> +}
> +
>  static const VMStateDescription vmstate_virtio_gpu_scanouts = {
>  .name = "virtio-gpu-scanouts",
> -.version_id = 1,
> +.version_id = 2,
> +.minimum_version_id = 1,
>  .fields = (const VMStateField[]) {
>  VMSTATE_INT32(parent_obj.enable, struct VirtIOGPU),
>  VMSTATE_UINT32_EQUAL(parent_obj.conf.max_outputs,
>   struct VirtIOGPU, NULL),
> -VMSTATE_STRUCT_VARRAY_UINT32(parent_obj.scanout, struct VirtIOGPU,
> - parent_obj.conf.max_outputs, 1,
> - vmstate_virtio_gpu_scanout,
> - struct virtio_gpu_scanout),
> +VMSTATE_VSTRUCT_TEST_VARRAY_UINT32(parent_obj.scanout, struct 
> VirtIOGPU,
> +   vmstate_before_v2,
> +   parent_obj.conf.max_outputs, 1,
> +   vmstate_virtio_gpu_scanout,
> +   struct virtio_gpu_scanout, 1),
> +VMSTATE_VSTRUCT_TEST_VARRAY_UINT32(parent_obj.scanout, struct 
> VirtIOGPU,
> +   NULL,
> +   parent_obj.conf.max_outputs, 2,
> +   vmstate_virtio_gpu_scanout,
> +   struct virtio_gpu_scanout, 2),

Personally I really wished struct_version_id never existed..  After these
years we only have 1 user of it (hw/ipmi/isa_ipmi_kcs.c), and we need to
keep that working.  I'm wondering whether there's way we can avoid adding
one more user, and even more complicated..

I think I get the reasoning behind "we define the same thing twice", but
this is really tricky and definitely needs rich documents, meanwhiel all of
these seem to rely on so many small details: one set .field_exists
properly, one leaving it to NULL; also the two versionings used here for
both parent vmsd, and the struct, and for each entry we need to set
different versions to different fields..

Would it work if we only make the new fields under control with
vmstate_before_v2()?  IOW, making all below with
.field_exists=vmstate_before_v2, so skip below when machine type is old?

 VMSTATE_UINT32_V(fb.format, struct virtio_gpu_scanout, 2),
 VMSTATE_UINT32_V(fb.bytes_pp, struct virtio_gpu_scanout, 2),
 VMSTATE_UINT32_V(fb.width, struct virtio_gpu_scanout, 2),
 VMSTATE_UINT32_V(fb.height, struct virtio_gpu_scanout, 2),
 VMSTATE_UINT32_V(fb.stride, struct virtio_gpu_scanout, 2),
 VMSTATE_UINT32_V(fb.offset, struct virtio_gpu_scanout, 2),

Thanks,

-- 
Peter Xu




Re: [PATCH 1/1] vhost-vsock: add VIRTIO_F_RING_PACKED to feaure_bits

2024-05-07 Thread Halil Pasic
On Mon, 29 Apr 2024 13:33:34 +0200
Halil Pasic  wrote:

> Not having VIRTIO_F_RING_PACKED in feature_bits[] is a problem when the
> vhost-vsock device does not offer the feature bit VIRTIO_F_RING_PACKED
> but the in QEMU device is configured to try to use the packed layout
> (the virtio property "packed" is on).

polite ping



[PATCH 3/4] hw/char: Add QOM property for STM32L4x5 USART clock frequency

2024-05-07 Thread Inès Varhol
This QOM property will be used to check the clock frequency from QTests.

Signed-off-by: Inès Varhol 
---
 hw/char/stm32l4x5_usart.c | 16 ++--
 1 file changed, 14 insertions(+), 2 deletions(-)

diff --git a/hw/char/stm32l4x5_usart.c b/hw/char/stm32l4x5_usart.c
index fc5dcac0c4..5fb3874f35 100644
--- a/hw/char/stm32l4x5_usart.c
+++ b/hw/char/stm32l4x5_usart.c
@@ -26,6 +26,7 @@
 #include "hw/clock.h"
 #include "hw/irq.h"
 #include "hw/qdev-clock.h"
+#include "qapi/visitor.h"
 #include "hw/qdev-properties.h"
 #include "hw/qdev-properties-system.h"
 #include "hw/registerfields.h"
@@ -523,6 +524,14 @@ static Property stm32l4x5_usart_base_properties[] = {
 DEFINE_PROP_END_OF_LIST(),
 };
 
+static void clock_freq_get(Object *obj, Visitor *v,
+const char *name, void *opaque, Error **errp)
+{
+Stm32l4x5UsartBaseState *s = STM32L4X5_USART_BASE(obj);
+uint32_t clock_freq_hz = clock_get_hz(s->clk);
+visit_type_uint32(v, name, _freq_hz, errp);
+}
+
 static void stm32l4x5_usart_base_init(Object *obj)
 {
 Stm32l4x5UsartBaseState *s = STM32L4X5_USART_BASE(obj);
@@ -534,6 +543,9 @@ static void stm32l4x5_usart_base_init(Object *obj)
 sysbus_init_mmio(SYS_BUS_DEVICE(obj), >mmio);
 
 s->clk = qdev_init_clock_in(DEVICE(s), "clk", NULL, s, 0);
+
+object_property_add(obj, "clock-freq-hz", "uint32",
+clock_freq_get, NULL, NULL, NULL);
 }
 
 static int stm32l4x5_usart_base_post_load(void *opaque, int version_id)
@@ -546,8 +558,8 @@ static int stm32l4x5_usart_base_post_load(void *opaque, int 
version_id)
 
 static const VMStateDescription vmstate_stm32l4x5_usart_base = {
 .name = TYPE_STM32L4X5_USART_BASE,
-.version_id = 1,
-.minimum_version_id = 1,
+.version_id = 2,
+.minimum_version_id = 2,
 .post_load = stm32l4x5_usart_base_post_load,
 .fields = (VMStateField[]) {
 VMSTATE_UINT32(cr1, Stm32l4x5UsartBaseState),
-- 
2.43.2




[PATCH 4/4] tests/qtest: Check STM32L4x5 clock connections

2024-05-07 Thread Inès Varhol
For USART, GPIO and SYSCFG devices, check that clock frequency before
and after enabling the peripheral clock in RCC is correct.

Signed-off-by: Inès Varhol 
---
 tests/qtest/stm32l4x5.h | 40 +
 tests/qtest/stm32l4x5_gpio-test.c   | 23 +
 tests/qtest/stm32l4x5_syscfg-test.c | 19 --
 tests/qtest/stm32l4x5_usart-test.c  | 26 +++
 4 files changed, 106 insertions(+), 2 deletions(-)
 create mode 100644 tests/qtest/stm32l4x5.h

diff --git a/tests/qtest/stm32l4x5.h b/tests/qtest/stm32l4x5.h
new file mode 100644
index 00..b8ef6698b2
--- /dev/null
+++ b/tests/qtest/stm32l4x5.h
@@ -0,0 +1,40 @@
+/*
+ * QTest testcase header for STM32L4X5 :
+ * used for consolidating common objects in stm32l4x5_*-test.c
+ *
+ * Copyright (c) 2024 Arnaud Minier 
+ * Copyright (c) 2024 Inès Varhol 
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include "qemu/osdep.h"
+#include "libqtest.h"
+
+/*
+ * MSI (4 MHz) is used as system clock source after startup
+ * from Reset.
+ * AHB, APB1 and APB2 prescalers are set to 1 at reset.
+ */
+#define SYSCLK_FREQ_HZ 400
+#define RCC_AHB2ENR 0x4002104C
+#define RCC_APB1ENR1 0x40021058
+#define RCC_APB1ENR2 0x4002105C
+#define RCC_APB2ENR 0x40021060
+
+
+static inline uint32_t get_clock_freq_hz(QTestState *qts, const char *path)
+{
+uint32_t clock_freq_hz = 0;
+QDict *r;
+
+r = qtest_qmp(qts, "{ 'execute': 'qom-get', 'arguments':"
+" { 'path': %s, 'property': 'clock-freq-hz'} }", path);
+g_assert_false(qdict_haskey(r, "error"));
+clock_freq_hz = qdict_get_int(r, "return");
+qobject_unref(r);
+return clock_freq_hz;
+}
+
+
diff --git a/tests/qtest/stm32l4x5_gpio-test.c 
b/tests/qtest/stm32l4x5_gpio-test.c
index 72a7823406..5c62125736 100644
--- a/tests/qtest/stm32l4x5_gpio-test.c
+++ b/tests/qtest/stm32l4x5_gpio-test.c
@@ -10,6 +10,7 @@
 
 #include "qemu/osdep.h"
 #include "libqtest-single.h"
+#include "stm32l4x5.h"
 
 #define GPIO_BASE_ADDR 0x4800
 #define GPIO_SIZE  0x400
@@ -505,6 +506,26 @@ static void test_bsrr_brr(const void *data)
 gpio_writel(gpio, ODR, reset(gpio, ODR));
 }
 
+static void test_clock_enable(void)
+{
+/*
+ * For each GPIO, enable its clock in RCC
+ * and check that its clock frequency changes to SYSCLK_FREQ_HZ
+ */
+unsigned int gpio_id;
+
+for (uint32_t gpio = GPIO_A; gpio <= GPIO_H; gpio += GPIO_B - GPIO_A) {
+gpio_id = get_gpio_id(gpio);
+g_autofree char *path = g_strdup_printf("/machine/soc/gpio%c",
+gpio_id + 'a');
+g_assert_cmpuint(get_clock_freq_hz(global_qtest, path), ==, 0);
+/* Enable the gpio clock */
+writel(RCC_AHB2ENR, readl(RCC_AHB2ENR) | (0x1 << gpio_id));
+g_assert_cmpuint(get_clock_freq_hz(global_qtest, path), ==,
+ SYSCLK_FREQ_HZ);
+}
+}
+
 int main(int argc, char **argv)
 {
 int ret;
@@ -556,6 +577,8 @@ int main(int argc, char **argv)
 qtest_add_data_func("stm32l4x5/gpio/test_bsrr_brr2",
 test_data(GPIO_D, 0),
 test_bsrr_brr);
+qtest_add_func("stm32l4x5/gpio/test_clock_enable",
+   test_clock_enable);
 
 qtest_start("-machine b-l475e-iot01a");
 ret = g_test_run();
diff --git a/tests/qtest/stm32l4x5_syscfg-test.c 
b/tests/qtest/stm32l4x5_syscfg-test.c
index 506ca08bc2..2ff0d5e9e0 100644
--- a/tests/qtest/stm32l4x5_syscfg-test.c
+++ b/tests/qtest/stm32l4x5_syscfg-test.c
@@ -10,6 +10,7 @@
 
 #include "qemu/osdep.h"
 #include "libqtest-single.h"
+#include "stm32l4x5.h"
 
 #define SYSCFG_BASE_ADDR 0x4001
 #define SYSCFG_MEMRMP 0x00
@@ -26,7 +27,8 @@
 #define INVALID_ADDR 0x2C
 
 /* SoC forwards GPIOs to SysCfg */
-#define SYSCFG "/machine/soc"
+#define SOC "/machine/soc"
+#define SYSCFG "/machine/soc/syscfg"
 #define EXTI "/machine/soc/exti"
 
 static void syscfg_writel(unsigned int offset, uint32_t value)
@@ -41,7 +43,7 @@ static uint32_t syscfg_readl(unsigned int offset)
 
 static void syscfg_set_irq(int num, int level)
 {
-   qtest_set_irq_in(global_qtest, SYSCFG, NULL, num, level);
+   qtest_set_irq_in(global_qtest, SOC, NULL, num, level);
 }
 
 static void system_reset(void)
@@ -301,6 +303,17 @@ static void test_irq_gpio_multiplexer(void)
 syscfg_writel(SYSCFG_EXTICR1, 0x);
 }
 
+static void test_clock_enable(void)
+{
+g_assert_cmpuint(get_clock_freq_hz(global_qtest, SYSCFG), ==, 0);
+
+/* Enable SYSCFG clock */
+writel(RCC_APB2ENR, readl(RCC_APB2ENR) | (0x1 << 0));
+
+g_assert_cmpuint(get_clock_freq_hz(global_qtest, SYSCFG), ==,
+   SYSCLK_FREQ_HZ);
+}
+
 int main(int argc, char **argv)
 {
 int ret;
@@ -325,6 +338,8 @@ int main(int argc, char **argv)
test_irq_pin_multiplexer);
 

[PATCH 0/4] Check clock connection between STM32L4x5 RCC and peripherals

2024-05-07 Thread Inès Varhol
Among implemented STM32L4x5 devices, USART, GPIO and SYSCFG
have a clock source, but none has a corresponding test in QEMU.

This patch makes sure that all 3 devices create a clock,
have a QOM property to access the clock frequency,
and adds QTests checking that clock enable in RCC has the
expected results.

Philippe Mathieu-Daudé suggested the following :
".. We could add the clock properties
directly in qdev_init_clock_in(). Seems useful for the QTest
framework."

However Peter Maydell pointed out the following :
"...Mostly "frequency" properties on devices are for the case
where they *don't* have a Clock input and instead have
ad-hoc legacy handling where the board/SoC that creates the
device sets an integer property to define the input frequency
because it doesn't model the clock tree with Clock objects."

You both agree on the fact that replicating the code in the
different devices is a bad idea, what should be the
alternative?

Thank you for the reviews.

Changes from v1:
- upgrading `VMStateDescription` to version 2 to account for
`VMSTATE_CLOCK()`
- QTests : consolidating `get_clock_freq_hz()` in a header
and making appropriate changes in stm32l4x5q_*-test.c

Signed-off-by: Inès Varhol 

Inès Varhol (4):
  hw/misc: Create STM32L4x5 SYSCFG clock
  hw/gpio: Handle clock migration in STM32L4x5 gpios
  hw/char: Add QOM property for STM32L4x5 USART clock frequency
  tests/qtest: Check STM32L4x5 clock connections

 include/hw/misc/stm32l4x5_syscfg.h  |  1 +
 tests/qtest/stm32l4x5.h | 40 +
 hw/arm/stm32l4x5_soc.c  |  2 ++
 hw/char/stm32l4x5_usart.c   | 16 ++--
 hw/gpio/stm32l4x5_gpio.c|  6 +++--
 hw/misc/stm32l4x5_syscfg.c  | 30 --
 tests/qtest/stm32l4x5_gpio-test.c   | 23 +
 tests/qtest/stm32l4x5_syscfg-test.c | 19 --
 tests/qtest/stm32l4x5_usart-test.c  | 26 +++
 9 files changed, 155 insertions(+), 8 deletions(-)
 create mode 100644 tests/qtest/stm32l4x5.h

-- 
2.43.2




[PATCH 2/4] hw/gpio: Handle clock migration in STM32L4x5 gpios

2024-05-07 Thread Inès Varhol
STM32L4x5 GPIO wasn't migrating its clock.

Signed-off-by: Inès Varhol 
---
 hw/gpio/stm32l4x5_gpio.c | 6 --
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/hw/gpio/stm32l4x5_gpio.c b/hw/gpio/stm32l4x5_gpio.c
index 71bf5fddb2..30d8d6cba4 100644
--- a/hw/gpio/stm32l4x5_gpio.c
+++ b/hw/gpio/stm32l4x5_gpio.c
@@ -20,6 +20,7 @@
 #include "qemu/log.h"
 #include "hw/gpio/stm32l4x5_gpio.h"
 #include "hw/irq.h"
+#include "hw/clock.h"
 #include "hw/qdev-clock.h"
 #include "hw/qdev-properties.h"
 #include "qapi/visitor.h"
@@ -426,8 +427,8 @@ static void stm32l4x5_gpio_realize(DeviceState *dev, Error 
**errp)
 
 static const VMStateDescription vmstate_stm32l4x5_gpio = {
 .name = TYPE_STM32L4X5_GPIO,
-.version_id = 1,
-.minimum_version_id = 1,
+.version_id = 2,
+.minimum_version_id = 2,
 .fields = (VMStateField[]){
 VMSTATE_UINT32(moder, Stm32l4x5GpioState),
 VMSTATE_UINT32(otyper, Stm32l4x5GpioState),
@@ -441,6 +442,7 @@ static const VMStateDescription vmstate_stm32l4x5_gpio = {
 VMSTATE_UINT32(ascr, Stm32l4x5GpioState),
 VMSTATE_UINT16(disconnected_pins, Stm32l4x5GpioState),
 VMSTATE_UINT16(pins_connected_high, Stm32l4x5GpioState),
+VMSTATE_CLOCK(clk, Stm32l4x5GpioState),
 VMSTATE_END_OF_LIST()
 }
 };
-- 
2.43.2




[PATCH 1/4] hw/misc: Create STM32L4x5 SYSCFG clock

2024-05-07 Thread Inès Varhol
This commit creates a clock in STM32L4x5 SYSCFG and wires it up to the
corresponding clock from STM32L4x5 RCC.
A read-only QOM property allowing to read the clock frequency is added
(it will be used in a QTest).

Signed-off-by: Inès Varhol 
---

Hello,

Several people noticed that replicating the code in the
different devices is a bad idea (cf cover letter).
One proposition is to directly add the clock property
in `qdev_init_clock_in()`.
Would that be acceptable and are there other alternatives
(allowing to the clock frequency from a Qtest)?

Best regards,

Inès Varhol

 include/hw/misc/stm32l4x5_syscfg.h |  1 +
 hw/arm/stm32l4x5_soc.c |  2 ++
 hw/misc/stm32l4x5_syscfg.c | 30 --
 3 files changed, 31 insertions(+), 2 deletions(-)

diff --git a/include/hw/misc/stm32l4x5_syscfg.h 
b/include/hw/misc/stm32l4x5_syscfg.h
index 23bb564150..c450df2b9e 100644
--- a/include/hw/misc/stm32l4x5_syscfg.h
+++ b/include/hw/misc/stm32l4x5_syscfg.h
@@ -48,6 +48,7 @@ struct Stm32l4x5SyscfgState {
 uint32_t swpr2;
 
 qemu_irq gpio_out[GPIO_NUM_PINS];
+Clock *clk;
 };
 
 #endif
diff --git a/hw/arm/stm32l4x5_soc.c b/hw/arm/stm32l4x5_soc.c
index 38f7a2d5d9..fb2afa6cfe 100644
--- a/hw/arm/stm32l4x5_soc.c
+++ b/hw/arm/stm32l4x5_soc.c
@@ -236,6 +236,8 @@ static void stm32l4x5_soc_realize(DeviceState *dev_soc, 
Error **errp)
 
 /* System configuration controller */
 busdev = SYS_BUS_DEVICE(>syscfg);
+qdev_connect_clock_in(DEVICE(>syscfg), "clk",
+qdev_get_clock_out(DEVICE(&(s->rcc)), "syscfg-out"));
 if (!sysbus_realize(busdev, errp)) {
 return;
 }
diff --git a/hw/misc/stm32l4x5_syscfg.c b/hw/misc/stm32l4x5_syscfg.c
index a5a1ce2680..7e6125383e 100644
--- a/hw/misc/stm32l4x5_syscfg.c
+++ b/hw/misc/stm32l4x5_syscfg.c
@@ -26,6 +26,10 @@
 #include "trace.h"
 #include "hw/irq.h"
 #include "migration/vmstate.h"
+#include "hw/clock.h"
+#include "hw/qdev-clock.h"
+#include "qapi/visitor.h"
+#include "qapi/error.h"
 #include "hw/misc/stm32l4x5_syscfg.h"
 #include "hw/gpio/stm32l4x5_gpio.h"
 
@@ -202,6 +206,14 @@ static void stm32l4x5_syscfg_write(void *opaque, hwaddr 
addr,
 }
 }
 
+static void clock_freq_get(Object *obj, Visitor *v,
+const char *name, void *opaque, Error **errp)
+{
+Stm32l4x5SyscfgState *s = STM32L4X5_SYSCFG(obj);
+uint32_t clock_freq_hz = clock_get_hz(s->clk);
+visit_type_uint32(v, name, _freq_hz, errp);
+}
+
 static const MemoryRegionOps stm32l4x5_syscfg_ops = {
 .read = stm32l4x5_syscfg_read,
 .write = stm32l4x5_syscfg_write,
@@ -225,12 +237,24 @@ static void stm32l4x5_syscfg_init(Object *obj)
 qdev_init_gpio_in(DEVICE(obj), stm32l4x5_syscfg_set_irq,
   GPIO_NUM_PINS * NUM_GPIOS);
 qdev_init_gpio_out(DEVICE(obj), s->gpio_out, GPIO_NUM_PINS);
+s->clk = qdev_init_clock_in(DEVICE(s), "clk", NULL, s, 0);
+object_property_add(obj, "clock-freq-hz", "uint32", clock_freq_get, NULL,
+NULL, NULL);
+}
+
+static void stm32l4x5_syscfg_realize(DeviceState *dev, Error **errp)
+{
+Stm32l4x5SyscfgState *s = STM32L4X5_SYSCFG(dev);
+if (!clock_has_source(s->clk)) {
+error_setg(errp, "SYSCFG: clk input must be connected");
+return;
+}
 }
 
 static const VMStateDescription vmstate_stm32l4x5_syscfg = {
 .name = TYPE_STM32L4X5_SYSCFG,
-.version_id = 1,
-.minimum_version_id = 1,
+.version_id = 2,
+.minimum_version_id = 2,
 .fields = (VMStateField[]) {
 VMSTATE_UINT32(memrmp, Stm32l4x5SyscfgState),
 VMSTATE_UINT32(cfgr1, Stm32l4x5SyscfgState),
@@ -241,6 +265,7 @@ static const VMStateDescription vmstate_stm32l4x5_syscfg = {
 VMSTATE_UINT32(swpr, Stm32l4x5SyscfgState),
 VMSTATE_UINT32(skr, Stm32l4x5SyscfgState),
 VMSTATE_UINT32(swpr2, Stm32l4x5SyscfgState),
+VMSTATE_CLOCK(clk, Stm32l4x5SyscfgState),
 VMSTATE_END_OF_LIST()
 }
 };
@@ -251,6 +276,7 @@ static void stm32l4x5_syscfg_class_init(ObjectClass *klass, 
void *data)
 ResettableClass *rc = RESETTABLE_CLASS(klass);
 
 dc->vmsd = _stm32l4x5_syscfg;
+dc->realize = stm32l4x5_syscfg_realize;
 rc->phases.hold = stm32l4x5_syscfg_hold_reset;
 }
 
-- 
2.43.2




[PATCH v13 1/6] ui/gtk: Check if fence_fd is equal to or greater than 0

2024-05-07 Thread dongwon . kim
From: Dongwon Kim 

'fence_fd' needs to be validated always before being referenced
And the passing condition should include '== 0' as 0 is a valid
value for the file descriptor.

Suggested-by: Marc-André Lureau 
Reviewed-by: Daniel P. Berrangé 
Cc: Philippe Mathieu-Daudé 
Cc: Daniel P. Berrangé 
Cc: Vivek Kasireddy 
Signed-off-by: Dongwon Kim 
---
 ui/gtk-egl.c |  2 +-
 ui/gtk-gl-area.c |  2 +-
 ui/gtk.c | 10 ++
 3 files changed, 8 insertions(+), 6 deletions(-)

diff --git a/ui/gtk-egl.c b/ui/gtk-egl.c
index 3af5ac5bcf..955234429d 100644
--- a/ui/gtk-egl.c
+++ b/ui/gtk-egl.c
@@ -99,7 +99,7 @@ void gd_egl_draw(VirtualConsole *vc)
 #ifdef CONFIG_GBM
 if (dmabuf) {
 egl_dmabuf_create_fence(dmabuf);
-if (dmabuf->fence_fd > 0) {
+if (dmabuf->fence_fd >= 0) {
 qemu_set_fd_handler(dmabuf->fence_fd, gd_hw_gl_flushed, NULL, 
vc);
 return;
 }
diff --git a/ui/gtk-gl-area.c b/ui/gtk-gl-area.c
index 52dcac161e..7fffd0544e 100644
--- a/ui/gtk-gl-area.c
+++ b/ui/gtk-gl-area.c
@@ -86,7 +86,7 @@ void gd_gl_area_draw(VirtualConsole *vc)
 #ifdef CONFIG_GBM
 if (dmabuf) {
 egl_dmabuf_create_fence(dmabuf);
-if (dmabuf->fence_fd > 0) {
+if (dmabuf->fence_fd >= 0) {
 qemu_set_fd_handler(dmabuf->fence_fd, gd_hw_gl_flushed, NULL, 
vc);
 return;
 }
diff --git a/ui/gtk.c b/ui/gtk.c
index 810d7fc796..7819a86321 100644
--- a/ui/gtk.c
+++ b/ui/gtk.c
@@ -597,10 +597,12 @@ void gd_hw_gl_flushed(void *vcon)
 VirtualConsole *vc = vcon;
 QemuDmaBuf *dmabuf = vc->gfx.guest_fb.dmabuf;
 
-qemu_set_fd_handler(dmabuf->fence_fd, NULL, NULL, NULL);
-close(dmabuf->fence_fd);
-dmabuf->fence_fd = -1;
-graphic_hw_gl_block(vc->gfx.dcl.con, false);
+if (dmabuf->fence_fd >= 0) {
+qemu_set_fd_handler(dmabuf->fence_fd, NULL, NULL, NULL);
+close(dmabuf->fence_fd);
+dmabuf->fence_fd = -1;
+graphic_hw_gl_block(vc->gfx.dcl.con, false);
+}
 }
 
 /** DisplayState Callbacks (opengl version) **/
-- 
2.34.1




[PATCH v13 4/6] ui/console: Use qemu_dmabuf_set_..() helpers instead

2024-05-07 Thread dongwon . kim
From: Dongwon Kim 

This commit updates all occurrences where these fields were
set directly have been updated to utilize helper functions.

v7: removed prefix, "dpy_gl_" from all helpers

v8: Introduction of helpers was removed as those were already added
by the previous commit

Suggested-by: Marc-André Lureau 
Reviewed-by: Marc-André Lureau 
Cc: Philippe Mathieu-Daudé 
Cc: Daniel P. Berrangé 
Cc: Vivek Kasireddy 
Signed-off-by: Dongwon Kim 
---
 ui/egl-helpers.c | 16 +---
 ui/gtk-egl.c |  4 ++--
 ui/gtk-gl-area.c |  4 ++--
 ui/gtk.c |  6 +++---
 4 files changed, 16 insertions(+), 14 deletions(-)

diff --git a/ui/egl-helpers.c b/ui/egl-helpers.c
index 3f96e63d25..99b2ebbe23 100644
--- a/ui/egl-helpers.c
+++ b/ui/egl-helpers.c
@@ -348,8 +348,8 @@ void egl_dmabuf_import_texture(QemuDmaBuf *dmabuf)
 return;
 }
 
-glGenTextures(1, >texture);
-texture = qemu_dmabuf_get_texture(dmabuf);
+glGenTextures(1, );
+qemu_dmabuf_set_texture(dmabuf, texture);
 glBindTexture(GL_TEXTURE_2D, texture);
 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
@@ -368,7 +368,7 @@ void egl_dmabuf_release_texture(QemuDmaBuf *dmabuf)
 }
 
 glDeleteTextures(1, );
-dmabuf->texture = 0;
+qemu_dmabuf_set_texture(dmabuf, 0);
 }
 
 void egl_dmabuf_create_sync(QemuDmaBuf *dmabuf)
@@ -382,7 +382,7 @@ void egl_dmabuf_create_sync(QemuDmaBuf *dmabuf)
 sync = eglCreateSyncKHR(qemu_egl_display,
 EGL_SYNC_NATIVE_FENCE_ANDROID, NULL);
 if (sync != EGL_NO_SYNC_KHR) {
-dmabuf->sync = sync;
+qemu_dmabuf_set_sync(dmabuf, sync);
 }
 }
 }
@@ -390,12 +390,14 @@ void egl_dmabuf_create_sync(QemuDmaBuf *dmabuf)
 void egl_dmabuf_create_fence(QemuDmaBuf *dmabuf)
 {
 void *sync = qemu_dmabuf_get_sync(dmabuf);
+int fence_fd;
 
 if (sync) {
-dmabuf->fence_fd = eglDupNativeFenceFDANDROID(qemu_egl_display,
-  sync);
+fence_fd = eglDupNativeFenceFDANDROID(qemu_egl_display,
+  sync);
+qemu_dmabuf_set_fence_fd(dmabuf, fence_fd);
 eglDestroySyncKHR(qemu_egl_display, sync);
-dmabuf->sync = NULL;
+qemu_dmabuf_set_sync(dmabuf, NULL);
 }
 }
 
diff --git a/ui/gtk-egl.c b/ui/gtk-egl.c
index 7a45daefa1..ec0bf45482 100644
--- a/ui/gtk-egl.c
+++ b/ui/gtk-egl.c
@@ -87,7 +87,7 @@ void gd_egl_draw(VirtualConsole *vc)
 if (!qemu_dmabuf_get_draw_submitted(dmabuf)) {
 return;
 } else {
-dmabuf->draw_submitted = false;
+qemu_dmabuf_set_draw_submitted(dmabuf, false);
 }
 }
 #endif
@@ -381,7 +381,7 @@ void gd_egl_flush(DisplayChangeListener *dcl,
 if (vc->gfx.guest_fb.dmabuf &&
 !qemu_dmabuf_get_draw_submitted(vc->gfx.guest_fb.dmabuf)) {
 graphic_hw_gl_block(vc->gfx.dcl.con, true);
-vc->gfx.guest_fb.dmabuf->draw_submitted = true;
+qemu_dmabuf_set_draw_submitted(vc->gfx.guest_fb.dmabuf, true);
 gtk_egl_set_scanout_mode(vc, true);
 gtk_widget_queue_draw_area(area, x, y, w, h);
 return;
diff --git a/ui/gtk-gl-area.c b/ui/gtk-gl-area.c
index 2d70280803..9a3f3d0d71 100644
--- a/ui/gtk-gl-area.c
+++ b/ui/gtk-gl-area.c
@@ -63,7 +63,7 @@ void gd_gl_area_draw(VirtualConsole *vc)
 if (!qemu_dmabuf_get_draw_submitted(dmabuf)) {
 return;
 } else {
-dmabuf->draw_submitted = false;
+qemu_dmabuf_set_draw_submitted(dmabuf, false);
 }
 }
 #endif
@@ -291,7 +291,7 @@ void gd_gl_area_scanout_flush(DisplayChangeListener *dcl,
 if (vc->gfx.guest_fb.dmabuf &&
 !qemu_dmabuf_get_draw_submitted(vc->gfx.guest_fb.dmabuf)) {
 graphic_hw_gl_block(vc->gfx.dcl.con, true);
-vc->gfx.guest_fb.dmabuf->draw_submitted = true;
+qemu_dmabuf_set_draw_submitted(vc->gfx.guest_fb.dmabuf, true);
 gtk_gl_area_set_scanout_mode(vc, true);
 }
 gtk_gl_area_queue_render(GTK_GL_AREA(vc->gfx.drawing_area));
diff --git a/ui/gtk.c b/ui/gtk.c
index 237c913b26..3a6832eb1b 100644
--- a/ui/gtk.c
+++ b/ui/gtk.c
@@ -598,11 +598,11 @@ void gd_hw_gl_flushed(void *vcon)
 QemuDmaBuf *dmabuf = vc->gfx.guest_fb.dmabuf;
 int fence_fd;
 
-if (dmabuf->fence_fd >= 0) {
-fence_fd = qemu_dmabuf_get_fence_fd(dmabuf);
+fence_fd = qemu_dmabuf_get_fence_fd(dmabuf);
+if (fence_fd >= 0) {
 qemu_set_fd_handler(fence_fd, NULL, NULL, NULL);
 close(fence_fd);
-dmabuf->fence_fd = -1;
+qemu_dmabuf_set_fence_fd(dmabuf, -1);
 graphic_hw_gl_block(vc->gfx.dcl.con, false);
 }
 }
-- 
2.34.1




[PATCH v13 2/6] ui/console: new dmabuf.h and dmabuf.c for QemuDmaBuf struct and helpers

2024-05-07 Thread dongwon . kim
From: Dongwon Kim 

New header and source files are added for containing QemuDmaBuf struct
definition and newly introduced helpers for creating/freeing the struct
and accessing its data.

v10: Change the license type for both dmabuf.h and dmabuf.c from MIT to
 GPL to be in line with QEMU's default license

v11: -- Added new helpers, qemu_dmabuf_close for closing dmabuf->fd,
qemu_dmabuf_dup_fd for duplicating dmabuf->fd
(Daniel P. Berrangé )

 -- Let qemu_dmabuf_fee to call qemu_dmabuf_close before freeing
the struct to make sure fd is closed.
(Daniel P. Berrangé )

v12: Not closing fd in qemu_dmabuf_free because there are cases fd
 should still be available even after the struct is destroyed
 (e.g. virtio-gpu: res->dmabuf_fd).

Suggested-by: Marc-André Lureau 
Reviewed-by: Marc-André Lureau 
Cc: Philippe Mathieu-Daudé 
Cc: Daniel P. Berrangé 
Cc: Vivek Kasireddy 
Signed-off-by: Dongwon Kim 
---
 include/ui/console.h |  20 +
 include/ui/dmabuf.h  |  66 ++
 ui/dmabuf.c  | 210 +++
 ui/meson.build   |   1 +
 4 files changed, 278 insertions(+), 19 deletions(-)
 create mode 100644 include/ui/dmabuf.h
 create mode 100644 ui/dmabuf.c

diff --git a/include/ui/console.h b/include/ui/console.h
index 0bc7a00ac0..a208a68b88 100644
--- a/include/ui/console.h
+++ b/include/ui/console.h
@@ -7,6 +7,7 @@
 #include "qapi/qapi-types-ui.h"
 #include "ui/input.h"
 #include "ui/surface.h"
+#include "ui/dmabuf.h"
 
 #define TYPE_QEMU_CONSOLE "qemu-console"
 OBJECT_DECLARE_TYPE(QemuConsole, QemuConsoleClass, QEMU_CONSOLE)
@@ -185,25 +186,6 @@ struct QEMUGLParams {
 int minor_ver;
 };
 
-typedef struct QemuDmaBuf {
-int   fd;
-uint32_t  width;
-uint32_t  height;
-uint32_t  stride;
-uint32_t  fourcc;
-uint64_t  modifier;
-uint32_t  texture;
-uint32_t  x;
-uint32_t  y;
-uint32_t  backing_width;
-uint32_t  backing_height;
-bool  y0_top;
-void  *sync;
-int   fence_fd;
-bool  allow_fences;
-bool  draw_submitted;
-} QemuDmaBuf;
-
 enum display_scanout {
 SCANOUT_NONE,
 SCANOUT_SURFACE,
diff --git a/include/ui/dmabuf.h b/include/ui/dmabuf.h
new file mode 100644
index 00..4198cdf85a
--- /dev/null
+++ b/include/ui/dmabuf.h
@@ -0,0 +1,66 @@
+/*
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ *
+ * QemuDmaBuf struct and helpers used for accessing its data
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#ifndef DMABUF_H
+#define DMABUF_H
+
+typedef struct QemuDmaBuf {
+int   fd;
+uint32_t  width;
+uint32_t  height;
+uint32_t  stride;
+uint32_t  fourcc;
+uint64_t  modifier;
+uint32_t  texture;
+uint32_t  x;
+uint32_t  y;
+uint32_t  backing_width;
+uint32_t  backing_height;
+bool  y0_top;
+void  *sync;
+int   fence_fd;
+bool  allow_fences;
+bool  draw_submitted;
+} QemuDmaBuf;
+
+QemuDmaBuf *qemu_dmabuf_new(uint32_t width, uint32_t height,
+uint32_t stride, uint32_t x,
+uint32_t y, uint32_t backing_width,
+uint32_t backing_height, uint32_t fourcc,
+uint64_t modifier, int dmabuf_fd,
+bool allow_fences, bool y0_top);
+void qemu_dmabuf_free(QemuDmaBuf *dmabuf);
+
+G_DEFINE_AUTOPTR_CLEANUP_FUNC(QemuDmaBuf, qemu_dmabuf_free);
+
+int qemu_dmabuf_get_fd(QemuDmaBuf *dmabuf);
+int qemu_dmabuf_dup_fd(QemuDmaBuf *dmabuf);
+void qemu_dmabuf_close(QemuDmaBuf *dmabuf);
+uint32_t qemu_dmabuf_get_width(QemuDmaBuf *dmabuf);
+uint32_t qemu_dmabuf_get_height(QemuDmaBuf *dmabuf);
+uint32_t qemu_dmabuf_get_stride(QemuDmaBuf *dmabuf);
+uint32_t qemu_dmabuf_get_fourcc(QemuDmaBuf *dmabuf);
+uint64_t qemu_dmabuf_get_modifier(QemuDmaBuf *dmabuf);
+uint32_t qemu_dmabuf_get_texture(QemuDmaBuf *dmabuf);
+uint32_t qemu_dmabuf_get_x(QemuDmaBuf *dmabuf);
+uint32_t qemu_dmabuf_get_y(QemuDmaBuf *dmabuf);
+uint32_t qemu_dmabuf_get_backing_width(QemuDmaBuf *dmabuf);
+uint32_t qemu_dmabuf_get_backing_height(QemuDmaBuf *dmabuf);
+bool qemu_dmabuf_get_y0_top(QemuDmaBuf *dmabuf);
+void *qemu_dmabuf_get_sync(QemuDmaBuf *dmabuf);
+int32_t qemu_dmabuf_get_fence_fd(QemuDmaBuf *dmabuf);
+bool qemu_dmabuf_get_allow_fences(QemuDmaBuf *dmabuf);
+bool qemu_dmabuf_get_draw_submitted(QemuDmaBuf *dmabuf);
+void qemu_dmabuf_set_texture(QemuDmaBuf *dmabuf, uint32_t texture);
+void qemu_dmabuf_set_fence_fd(QemuDmaBuf *dmabuf, int32_t fence_fd);
+void qemu_dmabuf_set_sync(QemuDmaBuf *dmabuf, void *sync);
+void qemu_dmabuf_set_draw_submitted(QemuDmaBuf *dmabuf, bool draw_submitted);
+void qemu_dmabuf_set_fd(QemuDmaBuf *dmabuf, int32_t fd);
+
+#endif
diff --git a/ui/dmabuf.c b/ui/dmabuf.c
new file mode 100644
index 00..e047d5ca26
--- /dev/null
+++ 

[PATCH v13 5/6] ui/console: Use qemu_dmabuf_new() and free() helpers instead

2024-05-07 Thread dongwon . kim
From: Dongwon Kim 

This commit introduces utility functions for the creation and deallocation
of QemuDmaBuf instances. Additionally, it updates all relevant sections
of the codebase to utilize these new utility functions.

v7: remove prefix, "dpy_gl_" from all helpers
qemu_dmabuf_free() returns without doing anything if input is null
(Daniel P. Berrangé )
call G_DEFINE_AUTOPTR_CLEANUP_FUNC for qemu_dmabuf_free()
(Daniel P. Berrangé )

v8: Introduction of helpers was removed as those were already added
by the previous commit

v9: set dmabuf->allow_fences to 'true' when dmabuf is created in
virtio_gpu_create_dmabuf()/virtio-gpu-udmabuf.c

removed unnecessary spaces were accidently added in the patch,
'ui/console: Use qemu_dmabuf_new() a...'

v11: Calling qemu_dmabuf_close was removed as closing dmabuf->fd will be
 done in qemu_dmabuf_free anyway.
 (Daniel P. Berrangé )

v12: --- Calling qemu_dmabuf_close separately as qemu_dmabuf_free doesn't
 do it.

 --- 'dmabuf' is now allocated space so it should be freed at the end of
 dbus_scanout_texture

v13: --- Immediately free dmabuf after it is released to prevent possible
 leaking of the ptr
 (Marc-André Lureau )

 --- Use g_autoptr macro to define *dmabuf for auto clean up instead of
 calling qemu_dmabuf_free
 (Marc-André Lureau )

Suggested-by: Marc-André Lureau 
Cc: Philippe Mathieu-Daudé 
Cc: Daniel P. Berrangé 
Cc: Vivek Kasireddy 
Signed-off-by: Dongwon Kim 
---
 include/hw/vfio/vfio-common.h   |  2 +-
 include/hw/virtio/virtio-gpu.h  |  4 ++--
 hw/display/vhost-user-gpu.c | 21 +++--
 hw/display/virtio-gpu-udmabuf.c | 24 +---
 hw/vfio/display.c   | 26 --
 ui/dbus-listener.c  | 28 
 6 files changed, 47 insertions(+), 58 deletions(-)

diff --git a/include/hw/vfio/vfio-common.h b/include/hw/vfio/vfio-common.h
index b9da6c08ef..d66e27db02 100644
--- a/include/hw/vfio/vfio-common.h
+++ b/include/hw/vfio/vfio-common.h
@@ -148,7 +148,7 @@ typedef struct VFIOGroup {
 } VFIOGroup;
 
 typedef struct VFIODMABuf {
-QemuDmaBuf buf;
+QemuDmaBuf *buf;
 uint32_t pos_x, pos_y, pos_updates;
 uint32_t hot_x, hot_y, hot_updates;
 int dmabuf_id;
diff --git a/include/hw/virtio/virtio-gpu.h b/include/hw/virtio/virtio-gpu.h
index ed44cdad6b..56d6e821bf 100644
--- a/include/hw/virtio/virtio-gpu.h
+++ b/include/hw/virtio/virtio-gpu.h
@@ -169,7 +169,7 @@ struct VirtIOGPUBaseClass {
 DEFINE_PROP_UINT32("yres", _state, _conf.yres, 800)
 
 typedef struct VGPUDMABuf {
-QemuDmaBuf buf;
+QemuDmaBuf *buf;
 uint32_t scanout_id;
 QTAILQ_ENTRY(VGPUDMABuf) next;
 } VGPUDMABuf;
@@ -238,7 +238,7 @@ struct VhostUserGPU {
 VhostUserBackend *vhost;
 int vhost_gpu_fd; /* closed by the chardev */
 CharBackend vhost_chr;
-QemuDmaBuf dmabuf[VIRTIO_GPU_MAX_SCANOUTS];
+QemuDmaBuf *dmabuf[VIRTIO_GPU_MAX_SCANOUTS];
 bool backend_blocked;
 };
 
diff --git a/hw/display/vhost-user-gpu.c b/hw/display/vhost-user-gpu.c
index 454e5afcff..744792cf78 100644
--- a/hw/display/vhost-user-gpu.c
+++ b/hw/display/vhost-user-gpu.c
@@ -249,6 +249,7 @@ vhost_user_gpu_handle_display(VhostUserGPU *g, 
VhostUserGpuMsg *msg)
 case VHOST_USER_GPU_DMABUF_SCANOUT: {
 VhostUserGpuDMABUFScanout *m = >payload.dmabuf_scanout;
 int fd = qemu_chr_fe_get_msgfd(>vhost_chr);
+uint64_t modifier = 0;
 QemuDmaBuf *dmabuf;
 
 if (m->scanout_id >= g->parent_obj.conf.max_outputs) {
@@ -261,27 +262,27 @@ vhost_user_gpu_handle_display(VhostUserGPU *g, 
VhostUserGpuMsg *msg)
 
 g->parent_obj.enable = 1;
 con = g->parent_obj.scanout[m->scanout_id].con;
-dmabuf = >dmabuf[m->scanout_id];
+dmabuf = g->dmabuf[m->scanout_id];
 qemu_dmabuf_close(dmabuf);
 dpy_gl_release_dmabuf(con, dmabuf);
+qemu_dmabuf_free(dmabuf);
 if (fd == -1) {
 dpy_gl_scanout_disable(con);
 break;
 }
-*dmabuf = (QemuDmaBuf) {
-.fd = fd,
-.width = m->fd_width,
-.height = m->fd_height,
-.stride = m->fd_stride,
-.fourcc = m->fd_drm_fourcc,
-.y0_top = m->fd_flags & VIRTIO_GPU_RESOURCE_FLAG_Y_0_TOP,
-};
 if (msg->request == VHOST_USER_GPU_DMABUF_SCANOUT2) {
 VhostUserGpuDMABUFScanout2 *m2 = >payload.dmabuf_scanout2;
-dmabuf->modifier = m2->modifier;
+modifier = m2->modifier;
 }
 
+dmabuf = qemu_dmabuf_new(m->fd_width, m->fd_height,
+ m->fd_stride, 0, 0, 0, 0,
+ m->fd_drm_fourcc, modifier,
+ fd, false, m->fd_flags &
+ VIRTIO_GPU_RESOURCE_FLAG_Y_0_TOP);
+
 dpy_gl_scanout_dmabuf(con, dmabuf);
+

[PATCH v13 6/6] ui/console: move QemuDmaBuf struct def to dmabuf.c

2024-05-07 Thread dongwon . kim
From: Dongwon Kim 

To complete privatizing process of QemuDmaBuf, QemuDmaBuf struct def
is moved to dmabuf.c

Suggested-by: Marc-André Lureau 
Reviewed-by: Marc-André Lureau 
Cc: Philippe Mathieu-Daudé 
Cc: Daniel P. Berrangé 
Cc: Vivek Kasireddy 
Signed-off-by: Dongwon Kim 
---
 include/ui/dmabuf.h | 19 +--
 ui/dmabuf.c | 19 +++
 2 files changed, 20 insertions(+), 18 deletions(-)

diff --git a/include/ui/dmabuf.h b/include/ui/dmabuf.h
index 4198cdf85a..dc74ba895a 100644
--- a/include/ui/dmabuf.h
+++ b/include/ui/dmabuf.h
@@ -10,24 +10,7 @@
 #ifndef DMABUF_H
 #define DMABUF_H
 
-typedef struct QemuDmaBuf {
-int   fd;
-uint32_t  width;
-uint32_t  height;
-uint32_t  stride;
-uint32_t  fourcc;
-uint64_t  modifier;
-uint32_t  texture;
-uint32_t  x;
-uint32_t  y;
-uint32_t  backing_width;
-uint32_t  backing_height;
-bool  y0_top;
-void  *sync;
-int   fence_fd;
-bool  allow_fences;
-bool  draw_submitted;
-} QemuDmaBuf;
+typedef struct QemuDmaBuf QemuDmaBuf;
 
 QemuDmaBuf *qemu_dmabuf_new(uint32_t width, uint32_t height,
 uint32_t stride, uint32_t x,
diff --git a/ui/dmabuf.c b/ui/dmabuf.c
index e047d5ca26..df7a09703f 100644
--- a/ui/dmabuf.c
+++ b/ui/dmabuf.c
@@ -10,6 +10,25 @@
 #include "qemu/osdep.h"
 #include "ui/dmabuf.h"
 
+struct QemuDmaBuf {
+int   fd;
+uint32_t  width;
+uint32_t  height;
+uint32_t  stride;
+uint32_t  fourcc;
+uint64_t  modifier;
+uint32_t  texture;
+uint32_t  x;
+uint32_t  y;
+uint32_t  backing_width;
+uint32_t  backing_height;
+bool  y0_top;
+void  *sync;
+int   fence_fd;
+bool  allow_fences;
+bool  draw_submitted;
+};
+
 QemuDmaBuf *qemu_dmabuf_new(uint32_t width, uint32_t height,
 uint32_t stride, uint32_t x,
 uint32_t y, uint32_t backing_width,
-- 
2.34.1




[PATCH v13 3/6] ui/console: Use qemu_dmabuf_get_..() helpers instead

2024-05-07 Thread dongwon . kim
From: Dongwon Kim 

This commit updates all instances where fields within the QemuDmaBuf
struct are directly accessed, replacing them with calls to these new
helper functions.

v6: fix typos in helper names in ui/spice-display.c

v7: removed prefix, "dpy_gl_" from all helpers

v8: Introduction of helpers was removed as those were already added
by the previous commit

v11: -- Use new qemu_dmabuf_close() instead of close(qemu_dmabuf_get_fd()).
(Daniel P. Berrangé )
 -- Use new qemu_dmabuf_dup_fd() instead of dup(qemu_dmabuf_get_fd()).
(Daniel P. Berrangé )

Suggested-by: Marc-André Lureau 
Reviewed-by: Marc-André Lureau 
Cc: Philippe Mathieu-Daudé 
Cc: Daniel P. Berrangé 
Cc: Vivek Kasireddy 
Signed-off-by: Dongwon Kim 
---
 hw/display/vhost-user-gpu.c |  5 +---
 hw/display/virtio-gpu-udmabuf.c |  7 +++--
 hw/vfio/display.c   | 12 +---
 ui/console.c|  4 +--
 ui/dbus-console.c   |  9 --
 ui/dbus-listener.c  | 43 +---
 ui/egl-headless.c   | 23 ++-
 ui/egl-helpers.c| 47 ++-
 ui/gtk-egl.c| 48 ---
 ui/gtk-gl-area.c| 37 
 ui/gtk.c|  6 ++--
 ui/spice-display.c  | 50 +++--
 12 files changed, 181 insertions(+), 110 deletions(-)

diff --git a/hw/display/vhost-user-gpu.c b/hw/display/vhost-user-gpu.c
index 709c8a02a1..454e5afcff 100644
--- a/hw/display/vhost-user-gpu.c
+++ b/hw/display/vhost-user-gpu.c
@@ -262,10 +262,7 @@ vhost_user_gpu_handle_display(VhostUserGPU *g, 
VhostUserGpuMsg *msg)
 g->parent_obj.enable = 1;
 con = g->parent_obj.scanout[m->scanout_id].con;
 dmabuf = >dmabuf[m->scanout_id];
-if (dmabuf->fd >= 0) {
-close(dmabuf->fd);
-dmabuf->fd = -1;
-}
+qemu_dmabuf_close(dmabuf);
 dpy_gl_release_dmabuf(con, dmabuf);
 if (fd == -1) {
 dpy_gl_scanout_disable(con);
diff --git a/hw/display/virtio-gpu-udmabuf.c b/hw/display/virtio-gpu-udmabuf.c
index d51184d658..c90eba281e 100644
--- a/hw/display/virtio-gpu-udmabuf.c
+++ b/hw/display/virtio-gpu-udmabuf.c
@@ -206,6 +206,7 @@ int virtio_gpu_update_dmabuf(VirtIOGPU *g,
 {
 struct virtio_gpu_scanout *scanout = >parent_obj.scanout[scanout_id];
 VGPUDMABuf *new_primary, *old_primary = NULL;
+uint32_t width, height;
 
 new_primary = virtio_gpu_create_dmabuf(g, scanout_id, res, fb, r);
 if (!new_primary) {
@@ -216,10 +217,10 @@ int virtio_gpu_update_dmabuf(VirtIOGPU *g,
 old_primary = g->dmabuf.primary[scanout_id];
 }
 
+width = qemu_dmabuf_get_width(_primary->buf);
+height = qemu_dmabuf_get_height(_primary->buf);
 g->dmabuf.primary[scanout_id] = new_primary;
-qemu_console_resize(scanout->con,
-new_primary->buf.width,
-new_primary->buf.height);
+qemu_console_resize(scanout->con, width, height);
 dpy_gl_scanout_dmabuf(scanout->con, _primary->buf);
 
 if (old_primary) {
diff --git a/hw/vfio/display.c b/hw/vfio/display.c
index 1aa440c663..7784502b53 100644
--- a/hw/vfio/display.c
+++ b/hw/vfio/display.c
@@ -260,8 +260,9 @@ static VFIODMABuf *vfio_display_get_dmabuf(VFIOPCIDevice 
*vdev,
 static void vfio_display_free_one_dmabuf(VFIODisplay *dpy, VFIODMABuf *dmabuf)
 {
 QTAILQ_REMOVE(>dmabuf.bufs, dmabuf, next);
+
+qemu_dmabuf_close(>buf);
 dpy_gl_release_dmabuf(dpy->con, >buf);
-close(dmabuf->buf.fd);
 g_free(dmabuf);
 }
 
@@ -286,6 +287,7 @@ static void vfio_display_dmabuf_update(void *opaque)
 VFIOPCIDevice *vdev = opaque;
 VFIODisplay *dpy = vdev->dpy;
 VFIODMABuf *primary, *cursor;
+uint32_t width, height;
 bool free_bufs = false, new_cursor = false;
 
 primary = vfio_display_get_dmabuf(vdev, DRM_PLANE_TYPE_PRIMARY);
@@ -296,10 +298,12 @@ static void vfio_display_dmabuf_update(void *opaque)
 return;
 }
 
+width = qemu_dmabuf_get_width(>buf);
+height = qemu_dmabuf_get_height(>buf);
+
 if (dpy->dmabuf.primary != primary) {
 dpy->dmabuf.primary = primary;
-qemu_console_resize(dpy->con,
-primary->buf.width, primary->buf.height);
+qemu_console_resize(dpy->con, width, height);
 dpy_gl_scanout_dmabuf(dpy->con, >buf);
 free_bufs = true;
 }
@@ -328,7 +332,7 @@ static void vfio_display_dmabuf_update(void *opaque)
 cursor->pos_updates = 0;
 }
 
-dpy_gl_update(dpy->con, 0, 0, primary->buf.width, primary->buf.height);
+dpy_gl_update(dpy->con, 0, 0, width, height);
 
 if (free_bufs) {
 vfio_display_free_dmabufs(vdev);
diff --git a/ui/console.c b/ui/console.c
index 43226c5c14..1b2cd0c736 100644
--- a/ui/console.c
+++ b/ui/console.c
@@ -1459,7 +1459,7 @@ int 

[PATCH v13 0/6] ui/console: Private QemuDmaBuf struct

2024-05-07 Thread dongwon . kim
From: Your Name 

This series introduces privacy enhancements to the QemuDmaBuf struct
and its contained data to bolster security. it accomplishes this by
introducing of helper functions for allocating, deallocating, and
accessing individual fields within the struct and replacing all direct
references to individual fields in the struct with methods using helpers
throughout the codebase.

This change was made based on a suggestion from Marc-André Lureau


(Resumitting same patch series with this new cover-leter)

v6: fixed some typos in patch -
ui/console: Introduce dpy_gl_qemu_dmabuf_get_..() helpers)

v7: included minor fix (ui/gtk: Check if fence_fd is equal to or greater than 0)
(Marc-André Lureau )

migrated all helpers and QemuDmaBuf struct into dmabuf.c and their 
prototypes
to dmabuf.h for better encapsulation (ui/dmabuf: New dmabuf.c and 
dmabuf.h..)
(Daniel P. Berrangé  and
 Marc-André Lureau )

removed 'dpy_gl' from all helpers' names
Defined autoptr clean up function for QemuDmaBuf*
(Daniel P. Berrangé )

Minor corrections

v8: Introduce new dmabuf.c and dmabuf.h and all helper functions in the second
patch in the series (ui/console: new dmabuf.h and dmabuf.c for QemuDma)
(Philippe Mathieu-Daudé )

v9: set dmabuf->allow_fences true when it is created in virtio-gpu-udmabuf

removed unnecessary spaces were added in the patch,
'ui/console: Use qemu_dmabuf_new() a...'

v10: Change the license type for both dmabuf.h and dmabuf.c from MIT to
 GPL to be in line with QEMU's default license
 (Daniel P. Berrangé )

v11: New helpers added - qemu_dmabuf_dup_fd, qemu_dmabuf_close for duplicating
 and closing dmabuf->fd. And use them in places where applicable.
 (Daniel P. Berrangé )

 qemu_dmabuf_free helper now close dmabuf->fd before freeing the struct to
 prevent any potential leakage (This eliminates the need for
 qemu_dmabuf_close in several places as qemu_dmabuf_close is done anyway.)
 (Daniel P. Berrangé )

v12: --- qemu_dmabuf_free does not include qemu_dmabuf_close as there are cases
 where fd still needs to be used even after QemuDmaBuf struct is
 destroyed (virtio-gpu: res->dmabuf_fd)

 --- 'dmabuf' is now allocated space so it should be freed at the end of
 dbus_scanout_texture

v13: --- Immediately free dmabuf after it is released to prevent possible
 leaking of the ptr
 (Marc-André Lureau )

 --- Use g_autoptr macro to define *dmabuf for auto clean up instead of
 calling qemu_dmabuf_free
 (Marc-André Lureau )

Dongwon Kim (6):
  ui/gtk: Check if fence_fd is equal to or greater than 0
  ui/console: new dmabuf.h and dmabuf.c for QemuDmaBuf struct and
helpers
  ui/console: Use qemu_dmabuf_get_..() helpers instead
  ui/console: Use qemu_dmabuf_set_..() helpers instead
  ui/console: Use qemu_dmabuf_new() and free() helpers instead
  ui/console: move QemuDmaBuf struct def to dmabuf.c

 include/hw/vfio/vfio-common.h   |   2 +-
 include/hw/virtio/virtio-gpu.h  |   4 +-
 include/ui/console.h|  20 +--
 include/ui/dmabuf.h |  49 +++
 hw/display/vhost-user-gpu.c |  26 ++--
 hw/display/virtio-gpu-udmabuf.c |  27 ++--
 hw/vfio/display.c   |  32 ++---
 ui/console.c|   4 +-
 ui/dbus-console.c   |   9 +-
 ui/dbus-listener.c  |  71 +-
 ui/dmabuf.c | 229 
 ui/egl-headless.c   |  23 +++-
 ui/egl-helpers.c|  59 
 ui/gtk-egl.c|  52 +---
 ui/gtk-gl-area.c|  41 --
 ui/gtk.c|  12 +-
 ui/spice-display.c  |  50 ---
 ui/meson.build  |   1 +
 18 files changed, 518 insertions(+), 193 deletions(-)
 create mode 100644 include/ui/dmabuf.h
 create mode 100644 ui/dmabuf.c

-- 
2.34.1




Re: [PULL 00/26] target/i386 changes for 2024-05-07

2024-05-07 Thread Richard Henderson

On 5/7/24 03:55, Paolo Bonzini wrote:

The following changes since commit e116b92d01c2cd75957a9f8ad1d4932292867b81:

   Merge tag 'qemu-sparc-20240506' ofhttps://github.com/mcayland/qemu  into 
staging (2024-05-06 10:19:56 -0700)

are available in the Git repository at:

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

for you to fetch changes up to d4e6d40c36071c287199c072cd5d296091ee5968:

   target/i386: remove duplicate prefix decoding (2024-05-07 08:53:26 +0200)


* target/i386/tcg: conversion of one byte opcodes to table-based decoder


Applied, thanks.  Please update https://wiki.qemu.org/ChangeLog/9.1 as 
appropriate.


r~




Re: [PATCH] qemu-io: add cvtnum() error handling for zone commands

2024-05-07 Thread Sam Li
Stefan Hajnoczi  于2024年5月7日周二 20:06写道:
>
> cvtnum() parses positive int64_t values and returns a negative errno on
> failure. Print errors and return early when cvtnum() fails.
>
> While we're at it, also reject nr_zones values greater or equal to 2^32
> since they cannot be represented.
>
> Reported-by: Peter Maydell 
> Cc: Sam Li 
> Signed-off-by: Stefan Hajnoczi 
> ---
>  qemu-io-cmds.c | 48 +++-
>  1 file changed, 47 insertions(+), 1 deletion(-)

Reviewed-by: Sam Li 

Hi Stefan,

Thank you for fixing that. I've been a little busy with moving house lately :)

Sam



[PATCH] qemu-io: add cvtnum() error handling for zone commands

2024-05-07 Thread Stefan Hajnoczi
cvtnum() parses positive int64_t values and returns a negative errno on
failure. Print errors and return early when cvtnum() fails.

While we're at it, also reject nr_zones values greater or equal to 2^32
since they cannot be represented.

Reported-by: Peter Maydell 
Cc: Sam Li 
Signed-off-by: Stefan Hajnoczi 
---
 qemu-io-cmds.c | 48 +++-
 1 file changed, 47 insertions(+), 1 deletion(-)

diff --git a/qemu-io-cmds.c b/qemu-io-cmds.c
index f5d7202a13..e2fab57183 100644
--- a/qemu-io-cmds.c
+++ b/qemu-io-cmds.c
@@ -1739,12 +1739,26 @@ static int zone_report_f(BlockBackend *blk, int argc, 
char **argv)
 {
 int ret;
 int64_t offset;
+int64_t val;
 unsigned int nr_zones;
 
 ++optind;
 offset = cvtnum(argv[optind]);
+if (offset < 0) {
+print_cvtnum_err(offset, argv[optind]);
+return offset;
+}
 ++optind;
-nr_zones = cvtnum(argv[optind]);
+val = cvtnum(argv[optind]);
+if (val < 0) {
+print_cvtnum_err(val, argv[optind]);
+return val;
+}
+if (val > UINT_MAX) {
+printf("Number of zones must be less than 2^32\n");
+return -ERANGE;
+}
+nr_zones = val;
 
 g_autofree BlockZoneDescriptor *zones = NULL;
 zones = g_new(BlockZoneDescriptor, nr_zones);
@@ -1780,8 +1794,16 @@ static int zone_open_f(BlockBackend *blk, int argc, char 
**argv)
 int64_t offset, len;
 ++optind;
 offset = cvtnum(argv[optind]);
+if (offset < 0) {
+print_cvtnum_err(offset, argv[optind]);
+return offset;
+}
 ++optind;
 len = cvtnum(argv[optind]);
+if (len < 0) {
+print_cvtnum_err(len, argv[optind]);
+return len;
+}
 ret = blk_zone_mgmt(blk, BLK_ZO_OPEN, offset, len);
 if (ret < 0) {
 printf("zone open failed: %s\n", strerror(-ret));
@@ -1805,8 +1827,16 @@ static int zone_close_f(BlockBackend *blk, int argc, 
char **argv)
 int64_t offset, len;
 ++optind;
 offset = cvtnum(argv[optind]);
+if (offset < 0) {
+print_cvtnum_err(offset, argv[optind]);
+return offset;
+}
 ++optind;
 len = cvtnum(argv[optind]);
+if (len < 0) {
+print_cvtnum_err(len, argv[optind]);
+return len;
+}
 ret = blk_zone_mgmt(blk, BLK_ZO_CLOSE, offset, len);
 if (ret < 0) {
 printf("zone close failed: %s\n", strerror(-ret));
@@ -1830,8 +1860,16 @@ static int zone_finish_f(BlockBackend *blk, int argc, 
char **argv)
 int64_t offset, len;
 ++optind;
 offset = cvtnum(argv[optind]);
+if (offset < 0) {
+print_cvtnum_err(offset, argv[optind]);
+return offset;
+}
 ++optind;
 len = cvtnum(argv[optind]);
+if (len < 0) {
+print_cvtnum_err(len, argv[optind]);
+return len;
+}
 ret = blk_zone_mgmt(blk, BLK_ZO_FINISH, offset, len);
 if (ret < 0) {
 printf("zone finish failed: %s\n", strerror(-ret));
@@ -1855,8 +1893,16 @@ static int zone_reset_f(BlockBackend *blk, int argc, 
char **argv)
 int64_t offset, len;
 ++optind;
 offset = cvtnum(argv[optind]);
+if (offset < 0) {
+print_cvtnum_err(offset, argv[optind]);
+return offset;
+}
 ++optind;
 len = cvtnum(argv[optind]);
+if (len < 0) {
+print_cvtnum_err(len, argv[optind]);
+return len;
+}
 ret = blk_zone_mgmt(blk, BLK_ZO_RESET, offset, len);
 if (ret < 0) {
 printf("zone reset failed: %s\n", strerror(-ret));
-- 
2.45.0




[PATCH] gitlab: Update msys2-64bit runner tags

2024-05-07 Thread Richard Henderson
Gitlab has deprecated and removed support for windows-1809
and shared-windows.  Update to saas-windows-medium-amd64 per

https://about.gitlab.com/blog/2024/01/22/windows-2022-support-for-gitlab-saas-runners/

Signed-off-by: Richard Henderson 
---
 .gitlab-ci.d/windows.yml | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/.gitlab-ci.d/windows.yml b/.gitlab-ci.d/windows.yml
index d26dbdd0c0..a83f23a786 100644
--- a/.gitlab-ci.d/windows.yml
+++ b/.gitlab-ci.d/windows.yml
@@ -1,9 +1,7 @@
 msys2-64bit:
   extends: .base_job_template
   tags:
-  - shared-windows
-  - windows
-  - windows-1809
+  - saas-windows-medium-amd64
   cache:
 key: "$CI_JOB_NAME"
 paths:
-- 
2.34.1




Re: [PATCH 1/4] hw/misc: Create STM32L4x5 SYSCFG clock

2024-05-07 Thread Inès Varhol



- Le 7 Mai 24, à 11:50, peter maydell peter.mayd...@linaro.org a écrit :

> On Sun, 5 May 2024 at 15:06, Inès Varhol  wrote:
>>
>> Signed-off-by: Inès Varhol 
> 
> In general you should try to avoid commits with no commit message.
> Sometimes there really isn't anything to say beyond what the
> subject line is, but that should be the exception rather than
> the usual thing.

Hello,

Understood, I'll add messages.

> 
>> ---
>>  include/hw/misc/stm32l4x5_syscfg.h |  1 +
>>  hw/arm/stm32l4x5_soc.c |  2 ++
>>  hw/misc/stm32l4x5_syscfg.c | 26 ++
>>  3 files changed, 29 insertions(+)
>>
>> diff --git a/include/hw/misc/stm32l4x5_syscfg.h
>> b/include/hw/misc/stm32l4x5_syscfg.h
>> index 23bb564150..c450df2b9e 100644
>> --- a/include/hw/misc/stm32l4x5_syscfg.h
>> +++ b/include/hw/misc/stm32l4x5_syscfg.h
>> @@ -48,6 +48,7 @@ struct Stm32l4x5SyscfgState {
>>  uint32_t swpr2;
>>
>>  qemu_irq gpio_out[GPIO_NUM_PINS];
>> +Clock *clk;
>>  };
>>
>>  #endif
>> diff --git a/hw/arm/stm32l4x5_soc.c b/hw/arm/stm32l4x5_soc.c
>> index 38f7a2d5d9..fb2afa6cfe 100644
>> --- a/hw/arm/stm32l4x5_soc.c
>> +++ b/hw/arm/stm32l4x5_soc.c
>> @@ -236,6 +236,8 @@ static void stm32l4x5_soc_realize(DeviceState *dev_soc,
>> Error **errp)
>>
>>  /* System configuration controller */
>>  busdev = SYS_BUS_DEVICE(>syscfg);
>> +qdev_connect_clock_in(DEVICE(>syscfg), "clk",
>> +qdev_get_clock_out(DEVICE(&(s->rcc)), "syscfg-out"));
>>  if (!sysbus_realize(busdev, errp)) {
>>  return;
>>  }
>> diff --git a/hw/misc/stm32l4x5_syscfg.c b/hw/misc/stm32l4x5_syscfg.c
>> index a5a1ce2680..a82864c33d 100644
>> --- a/hw/misc/stm32l4x5_syscfg.c
>> +++ b/hw/misc/stm32l4x5_syscfg.c
>> @@ -26,6 +26,10 @@
>>  #include "trace.h"
>>  #include "hw/irq.h"
>>  #include "migration/vmstate.h"
>> +#include "hw/clock.h"
>> +#include "hw/qdev-clock.h"
>> +#include "qapi/visitor.h"
>> +#include "qapi/error.h"
>>  #include "hw/misc/stm32l4x5_syscfg.h"
>>  #include "hw/gpio/stm32l4x5_gpio.h"
>>
>> @@ -202,6 +206,14 @@ static void stm32l4x5_syscfg_write(void *opaque, hwaddr
>> addr,
>>  }
>>  }
>>
>> +static void clock_freq_get(Object *obj, Visitor *v,
>> +const char *name, void *opaque, Error **errp)
>> +{
>> +Stm32l4x5SyscfgState *s = STM32L4X5_SYSCFG(obj);
>> +uint32_t clock_freq_hz = clock_get_hz(s->clk);
>> +visit_type_uint32(v, name, _freq_hz, errp);
>> +}
>> +
>>  static const MemoryRegionOps stm32l4x5_syscfg_ops = {
>>  .read = stm32l4x5_syscfg_read,
>>  .write = stm32l4x5_syscfg_write,
>> @@ -225,6 +237,18 @@ static void stm32l4x5_syscfg_init(Object *obj)
>>  qdev_init_gpio_in(DEVICE(obj), stm32l4x5_syscfg_set_irq,
>>GPIO_NUM_PINS * NUM_GPIOS);
>>  qdev_init_gpio_out(DEVICE(obj), s->gpio_out, GPIO_NUM_PINS);
>> +s->clk = qdev_init_clock_in(DEVICE(s), "clk", NULL, s, 0);
>> +object_property_add(obj, "clock-freq-hz", "uint32", clock_freq_get, 
>> NULL,
>> +NULL, NULL);
> 
> Why do we need this property? The clock on this device is an input,
> so the device doesn't control its frequency.

Using a QOM property allows to read the clock frequency from a QTest.
(npcm7xx_pwm-test.c does this, I didn't find other examples of reading a
frequency)

Best regards,

Inès Varhol




Re: [PATCH RFC 00/26] Multifd  device state transfer support with VFIO consumer

2024-05-07 Thread Avihai Horon



On 07/05/2024 19:13, Peter Xu wrote:

External email: Use caution opening links or attachments


On Tue, May 07, 2024 at 11:41:05AM +0300, Avihai Horon wrote:

Yes, I was working on parallel VFIO migration, but in a different approach
(not over multifd) which I'm not sure is relevant to this series.
I've been skimming over your discussions but haven't had the time to go over
Maciej's series thoroughly.
I will try to find time to do this next week and see if I can help.

IIUC your solution could also improve downtime, it's just that it bypasses
migration in general so from that POV a multifd-based solution is
preferred.

Fundamentally I think you share the goal more or less on allowing
concurrent vfio migrations, so it will be greatly helpful to have your
input / reviews, also making sure the ultimate solution will work for all
the use cases.


Yes, of course, I am planning to review and test this series once I have 
time.
As I previously mentioned [1], I'm in sync with Maciej and his work is 
the reason why I pulled back from mine.


Thanks.

[1] 
https://lore.kernel.org/qemu-devel/f1882336-15ac-40a4-b481-03efdb152...@nvidia.com/





Re: [PATCH v4 15/17] xen: mapcache: Remove assumption of RAMBlock with 0 offset

2024-05-07 Thread Edgar E. Iglesias
On Thu, May 2, 2024 at 10:02 PM Stefano Stabellini
 wrote:
>
> On Thu, 2 May 2024, Edgar E. Iglesias wrote:
> > On Thu, May 2, 2024 at 8:53 PM Stefano Stabellini
> >  wrote:
> > >
> > > +Xenia
> > >
> > > On Thu, 2 May 2024, Edgar E. Iglesias wrote:
> > > > On Wed, May 1, 2024 at 11:24 PM Stefano Stabellini
> > > >  wrote:
> > > > >
> > > > > On Tue, 30 Apr 2024, Edgar E. Iglesias wrote:
> > > > > > From: "Edgar E. Iglesias" 
> > > > > >
> > > > > > The current mapcache assumes that all memory is mapped
> > > > > > in a single RAM MR (the first one with offset 0). Remove
> > > > > > this assumption and propagate the offset to the mapcache
> > > > > > so it can do reverse mappings (from hostptr -> ram_addr).
> > > > > >
> > > > > > This is in preparation for adding grant mappings.
> > > > > >
> > > > > > Signed-off-by: Edgar E. Iglesias 
> > > > >
> > > > >
> > > > > Looking at xen_remap_bucket, it is only using address_index (without
> > > > > adding ram_offset) to map foreign memory. From xen_remap_bucket, I 
> > > > > would
> > > > > understand that address_index already includes the ram_offset.
> > > > >
> > > > > Meaning that if we want to map foreign mapping at address 0x5000, then
> > > > > address_index would be 0x5000, even if ram_offset is 0x1000.
> > > > >
> > > > > But then looking xen_ram_addr_from_mapcache_single ram_offset is added
> > > > > to paddr_index to calculate the physical address. So in that case we
> > > > > would want address_index to be 0x4000 and ram_offset to be 0x1000. But
> > > > > xen_remap_bucket would have to sum address_index and ram_offset to map
> > > > > foreign memory.
> > > > >
> > > > > So I am a bit confused, did I get it wrong? One more comment below.
> > > > >
> > > >
> > > > Thanks Stefano,
> > > >
> > > > I think the confusion is that this ram_addr_offset is not related to
> > > > guest address-space.
> > > > It's a QEMU internal thing and it shouldn't be included in the address
> > > > used to map foreign memory.
> > > > The mapcache can treat this ram_addr offset like a cookie that we keep
> > > > around to be able to do
> > > > reverse mappings from host pointers into ram_addr space
> > > > (xen_ram_addr_from_mapcache).
> > > >
> > > > The current mapcache implementation works because we've really only
> > > > been using foreign mappings
> > > > on RAMBlocks with offset 0. We're also creating RAM's such that the
> > > > offset into the RAM is also
> > > > the guest physical address, for x86 this is natural since RAM starts
> > > > at zero (for lowmem) but for
> > > > ARM we're creating larger than needed RAM's (GUEST_RAM0_BASE + 
> > > > ram-size) to
> > > > make this assumption true. Anyway, In this series I'm not addressing
> > > > this second assumption.
> > >
> > > Let's see if I understand correctly.
> > >
> > > The ram_addr space is an internal QEMU address space which is different
> > > from the guest physical address space and thus cannot and should not be
> > > used to do foreign mappings (foreign mapping hypercalls take a guest
> > > physical or a real physical address to map). Is that correct?
> > >
> > > If so, then I understand.
> > >
> >
> > Yes, that matches my understanding.
> >
> > >
> > >
> > > > There's a second call in physmem.c to xen_map_cache using the
> > > > block->offset as an address.
> > > > I was considering removing that second call since I can't see how it 
> > > > can work
> > > > (except perhaps in some specific use-case by luck?). Anyway, for now
> > > > I've left it unmodified.
> > >
> > > Yes, that code was written with the assumption that block->offset is an
> > > offset in the guest physical address space and could be used as a guest
> > > physical address. Actually, you might have spotted a real bug.
> > >
> > > The intent was for smaller regions (not the bit RAM region, things like
> > > a ROM region for instance) we could map them in full. So here we were
> > > trying to map the whole thing from start to finish using block->offset
> > > as start.
> > >
> > >
> > > > > > ---
> > > > > >  hw/xen/xen-mapcache.c | 25 ++---
> > > > > >  include/sysemu/xen-mapcache.h |  2 ++
> > > > > >  system/physmem.c  |  8 
> > > > > >  3 files changed, 24 insertions(+), 11 deletions(-)
> > > > > >
> > > > > > diff --git a/hw/xen/xen-mapcache.c b/hw/xen/xen-mapcache.c
> > > > > > index 09b5f36d9c..1b32d0c003 100644
> > > > > > --- a/hw/xen/xen-mapcache.c
> > > > > > +++ b/hw/xen/xen-mapcache.c
> > > > > > @@ -43,6 +43,9 @@ typedef struct MapCacheEntry {
> > > > > >  #define XEN_MAPCACHE_ENTRY_DUMMY (1 << 0)
> > > > > >  uint8_t flags;
> > > > > >  hwaddr size;
> > > > > > +
> > > > > > +/* Keep ram_addr offset for reverse mappings (hostptr -> 
> > > > > > ram_addr).  */
> > > > > > +ram_addr_t ram_offset;
> > > > > >  struct MapCacheEntry *next;
> > > > > >  } MapCacheEntry;
> > > > > >
> > > > > > @@ -165,7 +168,8 @@ static void xen_remap_bucket(MapCache *mc,
> > > > 

Re: [PATCH v6 0/9] TCG plugins new inline operations

2024-05-07 Thread Pierrick Bouvier

On 5/7/24 09:07, Alex Bennée wrote:

Pierrick Bouvier  writes:


This series implement two new operations for plugins:
- Store inline allows to write a specific value to a scoreboard.
- Conditional callback executes a callback only when a given condition is true.
   The condition is evaluated inline.

It's possible to mix various inline operations (add, store) with conditional
callbacks, allowing efficient "trap" based counters.

It builds on top of new scoreboard API, introduced in the previous
series.



Queued to plugins/next, thanks.



Thanks Alex.


Re: [PATCH v2 04/33] accel/tcg: Reorg translator_ld*

2024-05-07 Thread Richard Henderson

On 5/6/24 15:47, Philippe Mathieu-Daudé wrote:

On 25/4/24 01:31, Richard Henderson wrote:

Reorg translator_access into translator_ld, with a more
memcpy-ish interface.  If both pages are in ram, do not
go through the caller's slow path.

Assert that the access is within the two pages that we are
prepared to protect, per TranslationBlock.  Allow access
prior to pc_first, so long as it is within the first page.

Signed-off-by: Richard Henderson 
---
  accel/tcg/translator.c | 189 ++---
  1 file changed, 101 insertions(+), 88 deletions(-)




  uint64_t translator_ldq(CPUArchState *env, DisasContextBase *db, vaddr pc)
  {
-    uint64_t ret, plug;
-    void *p = translator_access(env, db, pc, sizeof(ret));
+    uint64_t raw, tgt;
-    if (p) {
-    plugin_insn_append(pc, p, sizeof(ret));
-    return ldq_p(p);
+    if (translator_ld(env, db, , pc, sizeof(raw))) {
+    tgt = tswap64(raw);
+    } else {
+    tgt = cpu_ldl_code(env, pc);


cpu_ldq_code() ?


Oops, yes indeed.  Fixed.

r~



Re: [PATCH 1/3] system/physmem: Replace qemu_mutex_lock() calls with QEMU_LOCK_GUARD

2024-05-07 Thread Richard Henderson

On 5/7/24 05:30, Philippe Mathieu-Daudé wrote:

Simplify cpu_[un]register_map_client() and cpu_notify_map_clients()
by replacing the pair of qemu_mutex_lock/qemu_mutex_unlock calls by
the WITH_QEMU_LOCK_GUARD() macro.

Signed-off-by: Philippe Mathieu-Daudé
---
  system/physmem.c | 9 +++--
  1 file changed, 3 insertions(+), 6 deletions(-)


Reviewed-by: Richard Henderson 

r~



Re: [PATCH v2] mem/cxl_type3: support 3, 6, 12 and 16 interleave ways

2024-05-07 Thread Jonathan Cameron via
On Tue, 7 May 2024 00:22:00 +
"Xingtao Yao (Fujitsu)"  wrote:

> > -Original Message-
> > From: Jonathan Cameron 
> > Sent: Tuesday, April 30, 2024 10:43 PM
> > To: Yao, Xingtao/姚 幸涛 
> > Cc: fan...@samsung.com; qemu-devel@nongnu.org
> > Subject: Re: [PATCH v2] mem/cxl_type3: support 3, 6, 12 and 16 interleave 
> > ways
> > 
> > On Wed, 24 Apr 2024 01:36:56 +
> > "Xingtao Yao (Fujitsu)"  wrote:
> >   
> > > ping.
> > >  
> > > > -Original Message-
> > > > From: Yao Xingtao 
> > > > Sent: Sunday, April 7, 2024 11:07 AM
> > > > To: jonathan.came...@huawei.com; fan...@samsung.com
> > > > Cc: qemu-devel@nongnu.org; Yao, Xingtao/姚 幸涛  
> >   
> > > > Subject: [PATCH v2] mem/cxl_type3: support 3, 6, 12 and 16 interleave 
> > > > ways
> > > >
> > > > Since the kernel does not check the interleave capability, a
> > > > 3-way, 6-way, 12-way or 16-way region can be create normally.
> > > >
> > > > Applications can access the memory of 16-way region normally because
> > > > qemu can convert hpa to dpa correctly for the power of 2 interleave
> > > > ways, after kernel implementing the check, this kind of region will
> > > > not be created any more.
> > > >
> > > > For non power of 2 interleave ways, applications could not access the
> > > > memory normally and may occur some unexpected behaviors, such as
> > > > segmentation fault.
> > > >
> > > > So implements this feature is needed.
> > > >
> > > > Link:
> > > >  
> > https://lore.kernel.org/linux-cxl/3e84b919-7631-d1db-3e1d-33000f3f3868@fujits
> >   
> > > > u.com/
> > > > Signed-off-by: Yao Xingtao 
> > > > ---
> > > >  hw/mem/cxl_type3.c | 18 ++
> > > >  1 file changed, 14 insertions(+), 4 deletions(-)
> > > >
> > > > diff --git a/hw/mem/cxl_type3.c b/hw/mem/cxl_type3.c
> > > > index b0a7e9f11b..d6ef784e96 100644
> > > > --- a/hw/mem/cxl_type3.c
> > > > +++ b/hw/mem/cxl_type3.c
> > > > @@ -805,10 +805,17 @@ static bool cxl_type3_dpa(CXLType3Dev *ct3d,  
> > hwaddr  
> > > > host_addr, uint64_t *dpa)
> > > >  continue;
> > > >  }
> > > >
> > > > -*dpa = dpa_base +
> > > > -((MAKE_64BIT_MASK(0, 8 + ig) & hpa_offset) |
> > > > - ((MAKE_64BIT_MASK(8 + ig + iw, 64 - 8 - ig - iw) & 
> > > > hpa_offset)  
> > > > -  >> iw));  
> > > > +if (iw < 8) {
> > > > +*dpa = dpa_base +
> > > > +((MAKE_64BIT_MASK(0, 8 + ig) & hpa_offset) |
> > > > + ((MAKE_64BIT_MASK(8 + ig + iw, 64 - 8 - ig - iw) &  
> > hpa_offset)  
> > > > +  >> iw));
> > > > +} else {
> > > > +*dpa = dpa_base +
> > > > +((MAKE_64BIT_MASK(0, 8 + ig) & hpa_offset) |
> > > > + MAKE_64BIT_MASK(ig + iw, 64 - ig - iw) & 
> > > > hpa_offset)
> > > > +   >> (ig + iw)) / 3) << (ig + 8)));
> > > > +}
> > > >
> > > >  return true;
> > > >  }
> > > > @@ -906,6 +913,9 @@ static void ct3d_reset(DeviceState *dev)
> > > >  uint32_t *write_msk =  
> > ct3d->cxl_cstate.crb.cache_mem_regs_write_mask;  
> > > >
> > > >  cxl_component_register_init_common(reg_state, write_msk,
> > > > CXL2_TYPE3_DEVICE);
> > > > +ARRAY_FIELD_DP32(reg_state, CXL_HDM_DECODER_CAPABILITY,
> > > > 3_6_12_WAY, 1);
> > > > +ARRAY_FIELD_DP32(reg_state, CXL_HDM_DECODER_CAPABILITY,
> > > > 16_WAY, 1);
> > > > +  
> > 
> > Why here rather than in hdm_reg_init_common()?
> > It's constant data and is currently being set to 0 in there.  
> 
> according to the CXL specifications (8.2.4.20.1 CXL HDM Decoder Capability 
> Register (Offset 00h)),
> this feature is only applicable to cxl.mem, upstream switch port and CXL host 
> bridges shall hardwrite
> these bits to 0.
> 
> so I think it would be more appropriate to set these bits here.
I don't follow. hdm_init_common() (sorry wrong function name above)
has some type specific stuff already to show how this can be done.
I'd prefer to minimize what we set directly in the ct3d_reset() call
because it loses the connection to the rest of the register setup.

Jonathan



Jonathan


> 
> >   
> > > >  cxl_device_register_init_t3(ct3d);
> > > >
> > > >  /*
> > > > --
> > > > 2.37.3  
> > >  
> 




Re: [PATCH-for-9.1 v2 2/3] migration: Remove RDMA protocol handling

2024-05-07 Thread Peter Xu
On Tue, May 07, 2024 at 01:50:43AM +, Gonglei (Arei) wrote:
> Hello,
> 
> > -Original Message-
> > From: Peter Xu [mailto:pet...@redhat.com]
> > Sent: Monday, May 6, 2024 11:18 PM
> > To: Gonglei (Arei) 
> > Cc: Daniel P. Berrangé ; Markus Armbruster
> > ; Michael Galaxy ; Yu Zhang
> > ; Zhijian Li (Fujitsu) ; Jinpu 
> > Wang
> > ; Elmar Gerdes ;
> > qemu-devel@nongnu.org; Yuval Shaia ; Kevin Wolf
> > ; Prasanna Kumar Kalever
> > ; Cornelia Huck ;
> > Michael Roth ; Prasanna Kumar Kalever
> > ; integrat...@gluster.org; Paolo Bonzini
> > ; qemu-bl...@nongnu.org; de...@lists.libvirt.org;
> > Hanna Reitz ; Michael S. Tsirkin ;
> > Thomas Huth ; Eric Blake ; Song
> > Gao ; Marc-André Lureau
> > ; Alex Bennée ;
> > Wainer dos Santos Moschetta ; Beraldo Leal
> > ; Pannengyuan ;
> > Xiexiangyou 
> > Subject: Re: [PATCH-for-9.1 v2 2/3] migration: Remove RDMA protocol handling
> > 
> > On Mon, May 06, 2024 at 02:06:28AM +, Gonglei (Arei) wrote:
> > > Hi, Peter
> > 
> > Hey, Lei,
> > 
> > Happy to see you around again after years.
> > 
> Haha, me too.
> 
> > > RDMA features high bandwidth, low latency (in non-blocking lossless
> > > network), and direct remote memory access by bypassing the CPU (As you
> > > know, CPU resources are expensive for cloud vendors, which is one of
> > > the reasons why we introduced offload cards.), which TCP does not have.
> > 
> > It's another cost to use offload cards, v.s. preparing more cpu resources?
> > 
> Software and hardware offload converged architecture is the way to go for all 
> cloud vendors 
> (Including comprehensive benefits in terms of performance, cost, security, 
> and innovation speed), 
> it's not just a matter of adding the resource of a DPU card.
> 
> > > In some scenarios where fast live migration is needed (extremely short
> > > interruption duration and migration duration) is very useful. To this
> > > end, we have also developed RDMA support for multifd.
> > 
> > Will any of you upstream that work?  I'm curious how intrusive would it be
> > when adding it to multifd, if it can keep only 5 exported functions like 
> > what
> > rdma.h does right now it'll be pretty nice.  We also want to make sure it 
> > works
> > with arbitrary sized loads and buffers, e.g. vfio is considering to add IO 
> > loads to
> > multifd channels too.
> > 
> 
> In fact, we sent the patchset to the community in 2021. Pls see:
> https://lore.kernel.org/all/20210203185906.GT2950@work-vm/T/

I wasn't aware of that for sure in the past..

Multifd has changed quite a bit in the last 9.0 release, that may not apply
anymore.  One thing to mention is please look at Dan's comment on possible
use of rsocket.h:

https://lore.kernel.org/all/zjjm6rcqs5eho...@redhat.com/

And Jinpu did help provide an initial test result over the library:

https://lore.kernel.org/qemu-devel/camgffek8wiknqmouyxcathgtiem2dwocf_w7t0vmcd-i30t...@mail.gmail.com/

It looks like we have a chance to apply that in QEMU.

> 
> 
> > One thing to note that the question here is not about a pure performance
> > comparison between rdma and nics only.  It's about help us make a decision
> > on whether to drop rdma, iow, even if rdma performs well, the community 
> > still
> > has the right to drop it if nobody can actively work and maintain it.
> > It's just that if nics can perform as good it's more a reason to drop, 
> > unless
> > companies can help to provide good support and work together.
> > 
> 
> We are happy to provide the necessary review and maintenance work for RDMA
> if the community needs it.
> 
> CC'ing Chuan Zheng.

I'm not sure whether you and Jinpu's team would like to work together and
provide a final solution for rdma over multifd.  It could be much simpler
than the original 2021 proposal if the rsocket API will work out.

Thanks,

-- 
Peter Xu




Re: [PATCH 2/3] vfio/migration: Emit VFIO device migration state change QAPI event

2024-05-07 Thread Avihai Horon



On 07/05/2024 18:51, Peter Xu wrote:

External email: Use caution opening links or attachments


On Tue, May 07, 2024 at 10:47:13AM +0300, Avihai Horon wrote:

While at it, another trivial comment is maybe it's nice to have a helper to
both update the vfio migration state, plus emitting events when necessary.

I think vfio_migration_set_state() does exactly that, no?

Ah yes, looks so.  It's just that I saw some common patterns, like:

===8<===
@@ -126,11 +167,13 @@ static int vfio_migration_set_state(VFIODevice *vbasedev,
  }

  migration->device_state = recover_state;
+vfio_migration_send_state_change_event(vbasedev);

  return ret;
  }

  migration->device_state = new_state;
+vfio_migration_send_state_change_event(vbasedev);
  if (mig_state->data_fd != -1) {
  if (migration->data_fd != -1) {
  /*
@@ -157,6 +200,7 @@ reset_device:
  }

  migration->device_state = VFIO_DEVICE_STATE_RUNNING;
+vfio_migration_send_state_change_event(vbasedev);

  return ret;
  }
===8<===

So maybe some more internal helpers?  It doesn't look like to cover all
updates to device_state, but I really didn't read into it.  Not a huge deal
really, feel free to keep it as-is if maintainers are happy.


Oh, I see what you mean.

Cedric, would you like me to add the following?

===8<===

--- a/hw/vfio/migration.c
+++ b/hw/vfio/migration.c
@@ -122,6 +122,14 @@ static void vfio_migration_send_event(VFIODevice 
*vbasedev)
 dev->id, qom_path, 
mig_state_to_qapi_state(migration->device_state));

 }

+static void set_state(VFIODevice *vbasedev, enum vfio_device_mig_state 
state)

+{
+    VFIOMigration *migration = vbasedev->migration;
+
+    migration->device_state = state;
+    vfio_migration_send_event(vbasedev);
+}
+
 static int vfio_migration_set_state(VFIODevice *vbasedev,
 enum vfio_device_mig_state new_state,
 enum vfio_device_mig_state 
recover_state)
@@ -171,14 +179,12 @@ static int vfio_migration_set_state(VFIODevice 
*vbasedev,

 goto reset_device;
 }

-    migration->device_state = recover_state;
-    vfio_migration_send_event(vbasedev);
+    set_state(vbasedev, recover_state);

 return ret;
 }

-    migration->device_state = new_state;
-    vfio_migration_send_event(vbasedev);
+    set_state(vbasedev, new_state);
 if (mig_state->data_fd != -1) {
 if (migration->data_fd != -1) {
 /*
@@ -204,8 +210,7 @@ reset_device:
  strerror(errno));
 }

-    migration->device_state = VFIO_DEVICE_STATE_RUNNING;
-    vfio_migration_send_event(vbasedev);
+    set_state(vbasedev, VFIO_DEVICE_STATE_RUNNING);

 return ret;
 }

===8<===




Re: [PULL 0/9] tcg + misc patch queue

2024-05-07 Thread Richard Henderson

On 5/7/24 07:33, Richard Henderson wrote:

The following changes since commit d4c453f64824bbeec56c7e72aa83019a7db70d9e:

   Merge tag 'for-upstream' ofhttps://gitlab.com/bonzini/qemu  into staging 
(2024-05-06 08:34:34 -0700)

are available in the Git repository at:

   https://gitlab.com/rth7680/qemu.git  tags/pull-tcg-20240507

for you to fetch changes up to f578b66e8c70ddea71d44db6e2c7abbcd757d684:

   gitlab: Streamline ubuntu-22.04-s390x (2024-05-06 23:40:36 -0700)


tcg: Add write_aofs to GVecGen3i
tcg/i386: Simplify immediate 8-bit logical vector shifts
tcg/i386: Optimize setcond of TST{EQ,NE} with 0x
tcg/optimize: Optimize setcond with zmask
accel/tcg: Introduce CF_BP_PAGE
target/sh4: Update DisasContextBase.insn_start
gitlab: Drop --static from s390x linux-user build
gitlab: Streamline ubuntu-22.04-s390x


Applied, thanks.  Please update https://wiki.qemu.org/ChangeLog/9.1 as 
appropriate.


r~




Re: [PATCH] loongarch64: move memory map to boot.c

2024-05-07 Thread Richard Henderson

On 5/7/24 07:51, Paolo Bonzini wrote:

Ensure that it can be used even if virt.c is not included in the build, as
is the case for --without-default-devices.

Signed-off-by: Paolo Bonzini
---
  include/hw/loongarch/boot.h | 10 ++
  include/hw/loongarch/virt.h | 10 --
  hw/loongarch/boot.c |  3 +++
  hw/loongarch/virt.c |  3 ---
  .gitlab-ci.d/buildtest.yml  |  2 +-
  5 files changed, 14 insertions(+), 14 deletions(-)


Acked-by: Richard Henderson 

r~



Re: [PATCH] misc: Use QEMU header path relative to include/ directory

2024-05-07 Thread Richard Henderson

On 5/7/24 07:27, Philippe Mathieu-Daudé wrote:

QEMU headers are relative to the include/ directory,
not to the project root directory. Remove "include/".

See also:
https://www.qemu.org/docs/master/devel/style.html#include-directives

Signed-off-by: Philippe Mathieu-Daudé
---
  hw/audio/virtio-snd.c   | 2 +-
  hw/rtc/ls7a_rtc.c   | 2 +-
  target/i386/gdbstub.c   | 2 +-
  tests/qtest/nvme-test.c | 2 +-
  tests/qtest/ufs-test.c  | 2 +-
  5 files changed, 5 insertions(+), 5 deletions(-)


Reviewed-by: Richard Henderson 




Re: [RFC PATCH v3 3/5] KVM: x86: Add notifications for Heki policy configuration and violation

2024-05-07 Thread Sean Christopherson
On Tue, May 07, 2024, Mickaël Salaün wrote:
> > Actually, potential bad/crazy idea.  Why does the _host_ need to define 
> > policy?
> > Linux already knows what assets it wants to (un)protect and when.  What's 
> > missing
> > is a way for the guest kernel to effectively deprivilege and re-authenticate
> > itself as needed.  We've been tossing around the idea of paired VMs+vCPUs to
> > support VTLs and SEV's VMPLs, what if we usurped/piggybacked those ideas, 
> > with a
> > bit of pKVM mixed in?
> > 
> > Borrowing VTL terminology, where VTL0 is the least privileged, userspace 
> > launches
> > the VM at VTL0.  At some point, the guest triggers the deprivileging 
> > sequence and
> > userspace creates VTL1.  Userpace also provides a way for VTL0 restrict 
> > access to
> > its memory, e.g. to effectively make the page tables for the kernel's 
> > direct map
> > writable only from VTL1, to make kernel text RO (or XO), etc.  And VTL0 
> > could then
> > also completely remove its access to code that changes CR0/CR4.
> > 
> > It would obviously require a _lot_ more upfront work, e.g. to isolate the 
> > kernel
> > text that modifies CR0/CR4 so that it can be removed from VTL0, but that 
> > should
> > be doable with annotations, e.g. tag relevant functions with __magic or 
> > whatever,
> > throw them in a dedicated section, and then free/protect the section(s) at 
> > the
> > appropriate time.
> > 
> > KVM would likely need to provide the ability to switch VTLs (or whatever 
> > they get
> > called), and host userspace would need to provide a decent amount of the 
> > backend
> > mechanisms and "core" policies, e.g. to manage VTL0 memory, teardown (turn 
> > off?)
> > VTL1 on kexec(), etc.  But everything else could live in the guest kernel 
> > itself.
> > E.g. to have CR pinning play nice with kexec(), toss the relevant kexec() 
> > code into
> > VTL1.  That way VTL1 can verify the kexec() target and tear itself down 
> > before
> > jumping into the new kernel. 
> > 
> > This is very off the cuff and have-wavy, e.g. I don't have much of an idea 
> > what
> > it would take to harden kernel text patching, but keeping the policy in the 
> > guest
> > seems like it'd make everything more tractable than trying to define an ABI
> > between Linux and a VMM that is rich and flexible enough to support all the
> > fancy things Linux does (and will do in the future).
> 
> Yes, we agree that the guest needs to manage its own policy.  That's why
> we implemented Heki for KVM this way, but without VTLs because KVM
> doesn't support them.
> 
> To sum up, is the VTL approach the only one that would be acceptable for
> KVM?  

Heh, that's not a question you want to be asking.  You're effectively asking me
to make an authorative, "final" decision on a topic which I am only passingly
familiar with.

But since you asked it... :-)  Probably?

I see a lot of advantages to a VTL/VSM-like approach:

 1. Provides Linux-as-a guest the flexibility it needs to meaningfully advance
its security, with the least amount of policy built into the guest/host ABI.

 2. Largely decouples guest policy from the host, i.e. should allow the guest to
evolve/update it's policy without needing to coordinate changes with the 
host.

 3. The KVM implementation can be generic enough to be reusable for other 
features.

 4. Other groups are already working on VTL-like support in KVM, e.g. for VSM
itself, and potentially for VMPL/SVSM support.

IMO, #2 is a *huge* selling point.  Not having to coordinate changes across
multiple code bases and/or organizations and/or maintainers is a big win for
velocity, long term maintenance, and probably the very viability of HEKI.

Providing the guest with the tools to define and implement its own policy means
end users don't have to way for some third party, e.g. CSPs, to deploy the
accompanying host-side changes, because there are no host-side changes.

And encapsulating everything in the guest drastically reduces the friction with
changes in the kernel that interact with hardening, both from a technical and a
social perspective.  I.e. giving the kernel (near) complete control over its
destiny minimizes the number of moving parts, and will be far, far easier to 
sell
to maintainers.  I would expect maintainers to react much more favorably to 
being
handed tools to harden the kernel, as opposed to being presented a set of APIs
that can be used to make the kernel compliant with _someone else's_ vision of
what kernel hardening should look like.

E.g. imagine a new feature comes along that requires overriding CR0/CR4 pinning
in a way that doesn't fit into existing policy.  If the VMM is involved in
defining/enforcing the CR pinning policy, then supporting said new feature would
require new guest/host ABI and an updated host VMM in order to make the new
feature compatible with HEKI.  Inevitably, even if everything goes smoothly from
an upstreaming perspective, that will result in guests that have to choose 

  1   2   3   4   >