Re: [PATCH 2/2] target/ppc/cpu_init: Synchronize HASHKEYR with KVM for migration

2024-06-03 Thread Nicholas Piggin
On Mon Jun 3, 2024 at 9:53 PM AEST, Shivaprasad G Bhat wrote:
> The patch enables HASHKEYR migration by hooking with the
> "KVM one reg" ID KVM_REG_PPC_HASHKEYR.
>
> Signed-off-by: Shivaprasad G Bhat 
> ---
>  linux-headers/asm-powerpc/kvm.h |1 +
>  target/ppc/cpu_init.c   |4 ++--
>  2 files changed, 3 insertions(+), 2 deletions(-)
>
> diff --git a/linux-headers/asm-powerpc/kvm.h b/linux-headers/asm-powerpc/kvm.h
> index fcb947f656..23a0af739c 100644
> --- a/linux-headers/asm-powerpc/kvm.h
> +++ b/linux-headers/asm-powerpc/kvm.h
> @@ -646,6 +646,7 @@ struct kvm_ppc_cpu_char {
>  #define KVM_REG_PPC_DAWR1(KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xc4)
>  #define KVM_REG_PPC_DAWRX1   (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xc5)
>  #define KVM_REG_PPC_DEXCR(KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xc6)
> +#define KVM_REG_PPC_HASHKEYR (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xc7)
>  
>  /* Transactional Memory checkpointed state:
>   * This is all GPRs, all VSX regs and a subset of SPRs
> diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c
> index b1422c2eab..cee0a609eb 100644
> --- a/target/ppc/cpu_init.c
> +++ b/target/ppc/cpu_init.c
> @@ -5805,10 +5805,10 @@ static void register_power10_hash_sprs(CPUPPCState 
> *env)
>  ((uint64_t)g_rand_int(rand) << 32) | (uint64_t)g_rand_int(rand);
>  g_rand_free(rand);
>  #endif
> -spr_register(env, SPR_HASHKEYR, "HASHKEYR",
> +spr_register_kvm(env, SPR_HASHKEYR, "HASHKEYR",
>  SPR_NOACCESS, SPR_NOACCESS,
>  _read_generic, _write_generic,
> -hashkeyr_initial_value);
> +KVM_REG_PPC_HASHKEYR, hashkeyr_initial_value);
>  spr_register_hv(env, SPR_HASHPKEYR, "HASHPKEYR",
>  SPR_NOACCESS, SPR_NOACCESS,
>  SPR_NOACCESS, SPR_NOACCESS,

Hmm... now that I look at it, the hashpkey value also needs to be set
in the machine and migrated, right? That looks broken. I *think* if we
make this spr_register_kvm_hv, and you will also need to add a KVM
API for the register, that should get it working becuse SPRs will
be migrated for us.

Thanks,
Nick



Re: [PATCH v2 4/4] tests/qtest/migration-test: Add a postcopy memfile test

2024-06-03 Thread Nicholas Piggin
On Fri May 31, 2024 at 11:34 PM AEST, Peter Xu wrote:
> On Thu, May 30, 2024 at 07:54:07PM +1000, Nicholas Piggin wrote:
> > Postcopy requires userfaultfd support, which requires tmpfs if a memory
> > file is used.
> > 
> > This adds back support for /dev/shm memory files, but adds preallocation
> > to skip environments where that mount is limited in size.
> > 
> > Signed-off-by: Nicholas Piggin 
>
> Thanks for doing this regardless.
>
> > ---
> >  tests/qtest/migration-test.c | 77 
> >  1 file changed, 69 insertions(+), 8 deletions(-)
> > 
> > diff --git a/tests/qtest/migration-test.c b/tests/qtest/migration-test.c
> > index 86eace354e..5078033ded 100644
> > --- a/tests/qtest/migration-test.c
> > +++ b/tests/qtest/migration-test.c
> > @@ -11,6 +11,7 @@
> >   */
> >  
> >  #include "qemu/osdep.h"
> > +#include "qemu/cutils.h"
> >  
> >  #include "libqtest.h"
> >  #include "qapi/qmp/qdict.h"
> > @@ -553,6 +554,7 @@ typedef struct {
> >   */
> >  bool hide_stderr;
> >  bool use_memfile;
> > +bool use_shm_memfile;
>
> Nitpick: when having both, it's slightly confusing on the name, e.g. not
> clear whether use_memfile needs to be set to true too if use_shm_memfile=true.
>
> Maybe "use_tmpfs_memfile" and "use_shm_memfile"?

Could be easy to confuse. It's not actually "tmpfs", it is the fs that
is mounted on /tmp :) tmpfs *is* shmfs in Linux. The intention was just
that if you don't specify then it's because you don't have a particular
requirement other than enough space.

> >  /* only launch the target process */
> >  bool only_target;
> >  /* Use dirty ring if true; dirty logging otherwise */
> > @@ -739,7 +741,62 @@ static int test_migrate_start(QTestState **from, 
> > QTestState **to,
> >  ignore_stderr = "";
> >  }
> >  
> > -if (args->use_memfile) {
> > +if (!qtest_has_machine(machine_alias)) {
> > +g_autofree char *msg = g_strdup_printf("machine %s not supported",
> > +   machine_alias);
> > +g_test_skip(msg);
> > +return -1;
> > +}
> > +
> > +if (args->use_shm_memfile) {
> > +#if defined(__NR_userfaultfd) && defined(__linux__)
>
> IIUC we only need defined(__linux__) as there's nothing to do with uffd yet?

I thought it was polite since it uses a few other Linux (or at least
POSIX) calls directly rather than go via the abstraction layer. Probably
it would never happen that something defines __NR_userfaultfd that does
not also have open and fallocate, but no harm?

> > +int fd;
> > +uint64_t size;
> > +
> > +if (getenv("GITLAB_CI")) {
> > +/*
> > + * Gitlab runners are limited to 64MB shm size and despite
> > + * pre-allocation there is concern that concurrent tests
> > + * could result in nondeterministic failures. Until all shm
> > + * usage in all CI tests is found to fail gracefully on
> > + * ENOSPC, it is safer to avoid large allocations for now.
> > + *
> > + * https://lore.kernel.org/qemu-devel/875xuwg4mx@suse.de/
> > + */
> > +g_test_skip("shm tests are not supported in Gitlab CI 
> > environment");
> > +return -1;
> > +}
>
> I'm not sure whether this is Fabiano's intention.  I'm wondering whether we
> can drop this and just let it still run there.
>
> Other tests not detecting avaiablility of shmem looks like a separate issue
> to be fixed to me, regardless of this.
>
> My wild guess is since we're doing memory_size+64K below then if test won't
> fail others won't either, as normally the shmem quota should normally be
> power of 2 anyway.. then it should always fit another few MBs if this one.
> While this test is ready to fail gracefully now.

Well if CI runners got upgraded to 256MB shm space under us, we might
start to succeed? I _think_ fallocate on tmpfs should be relatively
atomic in that it doesn't try to allocate space if the fs was too small,
but at least naive implementations can do it too, so I didn't want to
rely on it.

I'm fine to do what you and Fabiano prefer. If we commit this then later
remove this hunk, it would be easy to revert if it started to show up
fails. OTOH not too hard to add it in later either.

> > +
> > +if (!g_file_test("/dev/shm", G_FILE_

Re: [RFC PATCH 08/10] ppc/pnv: Invert the design for big-core machine modelling

2024-06-02 Thread Nicholas Piggin
On Thu May 30, 2024 at 5:46 PM AEST, Cédric Le Goater wrote:
>
> >>> @@ -157,6 +157,14 @@ static int pnv_dt_core(PnvChip *chip, PnvCore *pc, 
> >>> void *fdt)
> >>>
> >>>pnv_cc->processor_id(chip, pc->hwid, 0, , );
> >>>
> >>> +/* Only one DT node per (big) core */
> >>> +if (tir != 0) {
> >>> +g_assert(pc->big_core);
> >>> +g_assert(tir == 1);
> >>> +g_assert(pc->hwid & 1);
> >>> +return -1;
> >>
> >> return is -1 but it's not an error. right ?
> > 
> > Not an error just a "no CPU node to insert".
> > 
> > It's a bit ugly. Could return bool for yes/no and take a *offset
> > maybe?
>
> or we could pass the pa_features array  ?

That might work better. I'll try it.

> >>> +if (machine->smp.threads > 8) {
> >>> +error_report("Cannot support more than 8 threads/core "
> >>> + "on a powernv9/10  machine");
> >>> +exit(1);
> >>> +}
> >>> +if (machine->smp.threads % 2 == 1) {
> >>
> >> is_power_of_2()
> > 
> > It does have that check later in pnv_init(), but I wanted
> > to be careful that we're dividing by 2 below I think it makes
> > it more obvious (and big-core can't have 1 thread per big core).
>
> ok
>
>
> > 
> >>> @@ -1099,6 +1157,8 @@ static void pnv_power9_init(MachineState *machine)
> >>>
> >>>static void pnv_power10_init(MachineState *machine)
> >>>{
> >>> +PnvMachineState *pnv = PNV_MACHINE(machine);
> >>> +pnv->big_core_tbst_quirk = true;
> >>>pnv_power9_init(machine);
> >>>}
> >>>
> >>> @@ -1169,9 +1229,15 @@ static void pnv_processor_id_p9(PnvChip *chip,
> >>>uint32_t core_id, uint32_t thread_id,
> >>>uint32_t *pir, uint32_t *tir)
> >>>{
> >>> -if (chip->nr_threads == 8) {
> >>> -*pir = (chip->chip_id << 8) | ((thread_id & 1) << 2) | (core_id 
> >>> << 3) |
> >>> -   (thread_id >> 1);
> >>> +PnvMachineState *pnv = PNV_MACHINE(qdev_get_machine());
> >>
> >> arg. We should avoid these qdev_get_machine() calls. Could big_core be a
> >> chip property instead ?
> > 
> > We could, but per machine probably makes more sense. It's
> > funny there seems to be no good way to get machine from CPU.
> > Maybe we can just add a machine pointer in PnvChip?
>
>
> It would be easier/cleaner to propagate the machine settings to
> the chip unit and subunits. If I remember correctly, real HW has a
> scan init sequence doing something similar.

Sure. There wll be logic inside the core and chip that controls the
switch so it is not incorrect to model that way.

>
> > I'l probably leave that for another series and try to convert
> > most things.
> > 
> >>> +static bool pnv_machine_get_hb(Object *obj, Error **errp)
> >>> +{
> >>> +PnvMachineState *pnv = PNV_MACHINE(obj);
> >>> +
> >>> +return !!pnv->fw_load_addr;
> >>> +}
> >>> +
> >>> +static void pnv_machine_set_hb(Object *obj, bool value, Error **errp)
> >>> +{
> >>> +PnvMachineState *pnv = PNV_MACHINE(obj);
> >>> +
> >>> +if (value) {
> >>> +pnv->fw_load_addr = 0x800;
> >>> +}
> >>> +}
> >>
> >> we might want to get rid of the hostboot mode oneday. This was really
> >> experimental stuff.
> > 
> > Okay sure, I don't use it. Although we may want to run the
> > open source hostboot part of the firmware on QEMU one day,
> > we can always add back some options for it.
>
> It's not invasive either. Let's keep it. It use to work with a
> trimdown Linux image.

We'll keep it for now.

Thanks,
Nick



Re: [PULL 25/72] Adds migration support for Branch History Rolling Buffer (BHRB) internal state.

2024-06-02 Thread Nicholas Piggin
On Sat Jun 1, 2024 at 6:06 AM AEST, Fabiano Rosas wrote:
> Nicholas Piggin  writes:
>
> > From: Glenn Miles 
> >
> > Reviewed-by: Nicholas Piggin 
> > Signed-off-by: Glenn Miles 
> > Signed-off-by: Nicholas Piggin 
> > ---
> >  target/ppc/machine.c | 21 +
> >  1 file changed, 21 insertions(+)
> >
> > diff --git a/target/ppc/machine.c b/target/ppc/machine.c
> > index 6b6c31d903..731dd8df35 100644
> > --- a/target/ppc/machine.c
> > +++ b/target/ppc/machine.c
> > @@ -711,6 +711,26 @@ static const VMStateDescription vmstate_reservation = {
> >  }
> >  };
> >  
> > +#ifdef TARGET_PPC64
> > +static bool bhrb_needed(void *opaque)
> > +{
> > +PowerPCCPU *cpu = opaque;
> > +return (cpu->env.flags & POWERPC_FLAG_BHRB) != 0;
> > +}
> > +
> > +static const VMStateDescription vmstate_bhrb = {
> > +.name = "cpu/bhrb",
> > +.version_id = 1,
> > +.minimum_version_id = 1,
> > +.needed = bhrb_needed,
> > +.fields = (VMStateField[]) {
> > +VMSTATE_UINTTL(env.bhrb_offset, PowerPCCPU),
> > +VMSTATE_UINT64_ARRAY(env.bhrb, PowerPCCPU, BHRB_MAX_NUM_ENTRIES),
> > +VMSTATE_END_OF_LIST()
> > +}
> > +};
> > +#endif
> > +
> >  const VMStateDescription vmstate_ppc_cpu = {
> >  .name = "cpu",
> >  .version_id = 5,
> > @@ -756,6 +776,7 @@ const VMStateDescription vmstate_ppc_cpu = {
> >  #ifdef TARGET_PPC64
> >  _tm,
> >  _slb,
> > +_bhrb,
>
> Running some tests now that Nick re-enabled ppc for migration tests, I
> see that this new state breaks backward migrations:
>
> $ QTEST_TRACE="vmstate_*" \
>   QTEST_QEMU_BINARY_DST=../build-previous/qemu-system-ppc64 \
>   QTEST_QEMU_BINARY=./qemu-system-ppc64 \
>   ./tests/qtest/migration-test -p /ppc64/migration/precopy/tcp/plain
> ...
> vmstate_load_state_field cpu/slb:env.slb
> vmstate_n_elems env.slb: 64
> vmstate_subsection_load cpu/slb
> vmstate_subsection_load_bad cpu/slb: cpu/bhrb/(prefix)
> vmstate_load_state_end cpu/slb end/0
> vmstate_subsection_load_bad cpu: cpu/bhrb/(lookup)
> qemu-system-ppc64: error while loading state for instance 0x0 of device 'cpu'
> vmstate_downtime_checkpoint dst-precopy-loadvm-completed
> qemu-system-ppc64: load of migration failed: No such file or directory
>
> If you want to support backwards migration, then this needs to be
> fixed. Otherwise we can ignore it.


Hey Fabiano,

Thanks for picking that up, I missed it.

I think we could just say it's not needed, or only needed in
case we are doing replay. I will work on a fix.

Thanks,
Nick



[PATCH v2 4/4] tests/qtest/migration-test: Add a postcopy memfile test

2024-05-30 Thread Nicholas Piggin
Postcopy requires userfaultfd support, which requires tmpfs if a memory
file is used.

This adds back support for /dev/shm memory files, but adds preallocation
to skip environments where that mount is limited in size.

Signed-off-by: Nicholas Piggin 
---
 tests/qtest/migration-test.c | 77 
 1 file changed, 69 insertions(+), 8 deletions(-)

diff --git a/tests/qtest/migration-test.c b/tests/qtest/migration-test.c
index 86eace354e..5078033ded 100644
--- a/tests/qtest/migration-test.c
+++ b/tests/qtest/migration-test.c
@@ -11,6 +11,7 @@
  */
 
 #include "qemu/osdep.h"
+#include "qemu/cutils.h"
 
 #include "libqtest.h"
 #include "qapi/qmp/qdict.h"
@@ -553,6 +554,7 @@ typedef struct {
  */
 bool hide_stderr;
 bool use_memfile;
+bool use_shm_memfile;
 /* only launch the target process */
 bool only_target;
 /* Use dirty ring if true; dirty logging otherwise */
@@ -739,7 +741,62 @@ static int test_migrate_start(QTestState **from, 
QTestState **to,
 ignore_stderr = "";
 }
 
-if (args->use_memfile) {
+if (!qtest_has_machine(machine_alias)) {
+g_autofree char *msg = g_strdup_printf("machine %s not supported",
+   machine_alias);
+g_test_skip(msg);
+return -1;
+}
+
+if (args->use_shm_memfile) {
+#if defined(__NR_userfaultfd) && defined(__linux__)
+int fd;
+uint64_t size;
+
+if (getenv("GITLAB_CI")) {
+/*
+ * Gitlab runners are limited to 64MB shm size and despite
+ * pre-allocation there is concern that concurrent tests
+ * could result in nondeterministic failures. Until all shm
+ * usage in all CI tests is found to fail gracefully on
+ * ENOSPC, it is safer to avoid large allocations for now.
+ *
+ * https://lore.kernel.org/qemu-devel/875xuwg4mx@suse.de/
+ */
+g_test_skip("shm tests are not supported in Gitlab CI 
environment");
+return -1;
+}
+
+if (!g_file_test("/dev/shm", G_FILE_TEST_IS_DIR)) {
+g_test_skip("/dev/shm does not exist or is not a directory");
+return -1;
+}
+
+/*
+ * Pre-create and allocate the file here, because /dev/shm/
+ * is known to be limited in size in some places (e.g., Gitlab CI).
+ */
+memfile_path = g_strdup_printf("/dev/shm/qemu-%d", getpid());
+fd = open(memfile_path, O_WRONLY | O_CREAT | O_EXCL, S_IRUSR | 
S_IWUSR);
+if (fd == -1) {
+g_test_skip("/dev/shm file could not be created");
+return -1;
+}
+
+g_assert(qemu_strtosz(memory_size, NULL, ) == 0);
+size += 64*1024; /* QEMU may map a bit more memory for a guard page */
+
+if (fallocate(fd, 0, 0, size) == -1) {
+unlink(memfile_path);
+perror("could not alloc"); exit(1);
+g_test_skip("Could not allocate machine memory in /dev/shm");
+return -1;
+}
+close(fd);
+#else
+g_test_skip("userfaultfd is not supported");
+#endif
+} else if (args->use_memfile) {
 memfile_path = g_strdup_printf("/%s/qemu-%d", tmpfs, getpid());
 memfile_opts = g_strdup_printf(
 "-object memory-backend-file,id=mem0,size=%s"
@@ -751,12 +808,6 @@ static int test_migrate_start(QTestState **from, 
QTestState **to,
 kvm_opts = ",dirty-ring-size=4096";
 }
 
-if (!qtest_has_machine(machine_alias)) {
-g_autofree char *msg = g_strdup_printf("machine %s not supported", 
machine_alias);
-g_test_skip(msg);
-return -1;
-}
-
 machine = resolve_machine_version(machine_alias, QEMU_ENV_SRC,
   QEMU_ENV_DST);
 
@@ -807,7 +858,7 @@ static int test_migrate_start(QTestState **from, QTestState 
**to,
  * Remove shmem file immediately to avoid memory leak in test failed case.
  * It's valid because QEMU has already opened this file
  */
-if (args->use_memfile) {
+if (args->use_memfile || args->use_shm_memfile) {
 unlink(memfile_path);
 }
 
@@ -1275,6 +1326,15 @@ static void test_postcopy(void)
 test_postcopy_common();
 }
 
+static void test_postcopy_memfile(void)
+{
+MigrateCommon args = {
+.start.use_shm_memfile = true,
+};
+
+test_postcopy_common();
+}
+
 static void test_postcopy_suspend(void)
 {
 MigrateCommon args = {
@@ -3441,6 +3501,7 @@ int main(int argc, char **argv)
 
 if (has_uffd) {
 migration_test_add("/migration/postcopy/plain", test_postcopy);
+migration_test_add("/migration/postcopy/memfile", 
test_postcopy_memfile);
 migration_test_add("/migration/postcopy/recovery/plain",
test_postcopy_recovery);
 migration_test_add("/migration/postcopy/preempt/plain",
-- 
2.43.0




[PATCH v2 3/4] tests/qtest/migration-test: Fix and enable test_ignore_shared

2024-05-30 Thread Nicholas Piggin
This test is already starting to bitrot, so first remove it from ifdef
and fix compile issues. ppc64 transfers about 2MB, so bump the size
threshold too.

It was said to be broken on aarch64 but it may have been due to the
limited shm size under Gitlab CI. Now that it uses /tmp, enable it.

Cc: Yury Kotov 
Cc: Dr. David Alan Gilbert 
Signed-off-by: Nicholas Piggin 
---
 tests/qtest/migration-test.c | 11 +--
 1 file changed, 5 insertions(+), 6 deletions(-)

diff --git a/tests/qtest/migration-test.c b/tests/qtest/migration-test.c
index de380757be..86eace354e 100644
--- a/tests/qtest/migration-test.c
+++ b/tests/qtest/migration-test.c
@@ -1855,8 +1855,6 @@ static void test_precopy_unix_tls_x509_override_host(void)
 #endif /* CONFIG_TASN1 */
 #endif /* CONFIG_GNUTLS */
 
-#if 0
-/* Currently upset on aarch64 TCG */
 static void test_ignore_shared(void)
 {
 g_autofree char *uri = g_strdup_printf("unix:%s/migsocket", tmpfs);
@@ -1865,7 +1863,7 @@ static void test_ignore_shared(void)
 .use_memfile = true,
 };
 
-if (test_migrate_start(, , uri, false, true, NULL, NULL)) {
+if (test_migrate_start(, , uri, )) {
 return;
 }
 
@@ -1890,11 +1888,11 @@ static void test_ignore_shared(void)
 wait_for_migration_complete(from);
 
 /* Check whether shared RAM has been really skipped */
-g_assert_cmpint(read_ram_property_int(from, "transferred"), <, 1024 * 
1024);
+g_assert_cmpint(read_ram_property_int(from, "transferred"), <,
+   4 * 1024 * 1024);
 
 test_migrate_end(from, to, true);
 }
-#endif
 
 static void *
 test_migrate_xbzrle_start(QTestState *from,
@@ -3535,7 +3533,8 @@ int main(int argc, char **argv)
 #endif /* CONFIG_TASN1 */
 #endif /* CONFIG_GNUTLS */
 
-/* migration_test_add("/migration/ignore_shared", test_ignore_shared); */
+migration_test_add("/migration/ignore_shared", test_ignore_shared);
+
 #ifndef _WIN32
 migration_test_add("/migration/precopy/fd/tcp",
test_migrate_precopy_fd_socket);
-- 
2.43.0




[PATCH v2 2/4] tests/qtest/migration-test: Enable test_mode_reboot

2024-05-30 Thread Nicholas Piggin
Fabiano pointed out this test probably is not flaky, just that it could
not run under Gitlab CI due to very small shm filesystem size in that
environment.

Now that it has moved to use /tmp instead of /dev/shm files, enable it.

Signed-off-by: Nicholas Piggin 
---
 tests/qtest/migration-test.c | 10 +-
 1 file changed, 1 insertion(+), 9 deletions(-)

diff --git a/tests/qtest/migration-test.c b/tests/qtest/migration-test.c
index 8bbf45313d..de380757be 100644
--- a/tests/qtest/migration-test.c
+++ b/tests/qtest/migration-test.c
@@ -3469,15 +3469,7 @@ int main(int argc, char **argv)
test_precopy_file_offset);
 migration_test_add("/migration/precopy/file/offset/bad",
test_precopy_file_offset_bad);
-
-/*
- * Our CI system has problems with shared memory.
- * Don't run this test until we find a workaround.
- */
-if (getenv("QEMU_TEST_FLAKY_TESTS")) {
-migration_test_add("/migration/mode/reboot", test_mode_reboot);
-}
-
+migration_test_add("/migration/mode/reboot", test_mode_reboot);
 migration_test_add("/migration/precopy/file/mapped-ram",
test_precopy_file_mapped_ram);
 migration_test_add("/migration/precopy/file/mapped-ram/live",
-- 
2.43.0




[PATCH v2 1/4] tests/qtest/migration-test: Use regular file file for shared-memory tests

2024-05-30 Thread Nicholas Piggin
There is no need to use /dev/shm for file-backed memory devices, and
on Gitlab CI the tmpfs mount is too small to be usable for migration
tests. Switch to using a regular file in /tmp/ which will usually have
more space available.

Signed-off-by: Nicholas Piggin 
---
 tests/qtest/migration-test.c | 34 +++---
 1 file changed, 15 insertions(+), 19 deletions(-)

diff --git a/tests/qtest/migration-test.c b/tests/qtest/migration-test.c
index d6f5ceed80..8bbf45313d 100644
--- a/tests/qtest/migration-test.c
+++ b/tests/qtest/migration-test.c
@@ -552,7 +552,7 @@ typedef struct {
  * unconditionally, because it means the user would like to be verbose.
  */
 bool hide_stderr;
-bool use_shmem;
+bool use_memfile;
 /* only launch the target process */
 bool only_target;
 /* Use dirty ring if true; dirty logging otherwise */
@@ -672,21 +672,14 @@ static int test_migrate_start(QTestState **from, 
QTestState **to,
 g_autofree gchar *cmd_source = NULL;
 g_autofree gchar *cmd_target = NULL;
 const gchar *ignore_stderr;
-g_autofree char *shmem_opts = NULL;
-g_autofree char *shmem_path = NULL;
+g_autofree char *memfile_opts = NULL;
+g_autofree char *memfile_path = NULL;
 const char *kvm_opts = NULL;
 const char *arch = qtest_get_arch();
 const char *memory_size;
 const char *machine_alias, *machine_opts = "";
 g_autofree char *machine = NULL;
 
-if (args->use_shmem) {
-if (!g_file_test("/dev/shm", G_FILE_TEST_IS_DIR)) {
-g_test_skip("/dev/shm is not supported");
-return -1;
-}
-}
-
 dst_state = (QTestMigrationState) { };
 src_state = (QTestMigrationState) { };
 bootfile_create(tmpfs, args->suspend_me);
@@ -746,12 +739,12 @@ static int test_migrate_start(QTestState **from, 
QTestState **to,
 ignore_stderr = "";
 }
 
-if (args->use_shmem) {
-shmem_path = g_strdup_printf("/dev/shm/qemu-%d", getpid());
-shmem_opts = g_strdup_printf(
+if (args->use_memfile) {
+memfile_path = g_strdup_printf("/%s/qemu-%d", tmpfs, getpid());
+memfile_opts = g_strdup_printf(
 "-object memory-backend-file,id=mem0,size=%s"
 ",mem-path=%s,share=on -numa node,memdev=mem0",
-memory_size, shmem_path);
+memory_size, memfile_path);
 }
 
 if (args->use_dirty_ring) {
@@ -780,7 +773,7 @@ static int test_migrate_start(QTestState **from, QTestState 
**to,
  memory_size, tmpfs,
  arch_opts ? arch_opts : "",
  arch_source ? arch_source : "",
- shmem_opts ? shmem_opts : "",
+ memfile_opts ? memfile_opts : "",
  args->opts_source ? args->opts_source : "",
  ignore_stderr);
 if (!args->only_target) {
@@ -802,7 +795,7 @@ static int test_migrate_start(QTestState **from, QTestState 
**to,
  memory_size, tmpfs, uri,
  arch_opts ? arch_opts : "",
  arch_target ? arch_target : "",
- shmem_opts ? shmem_opts : "",
+ memfile_opts ? memfile_opts : "",
  args->opts_target ? args->opts_target : "",
  ignore_stderr);
 *to = qtest_init_with_env(QEMU_ENV_DST, cmd_target);
@@ -814,8 +807,8 @@ static int test_migrate_start(QTestState **from, QTestState 
**to,
  * Remove shmem file immediately to avoid memory leak in test failed case.
  * It's valid because QEMU has already opened this file
  */
-if (args->use_shmem) {
-unlink(shmem_path);
+if (args->use_memfile) {
+unlink(memfile_path);
 }
 
 return 0;
@@ -1868,6 +1861,9 @@ static void test_ignore_shared(void)
 {
 g_autofree char *uri = g_strdup_printf("unix:%s/migsocket", tmpfs);
 QTestState *from, *to;
+MigrateStart args = {
+.use_memfile = true,
+};
 
 if (test_migrate_start(, , uri, false, true, NULL, NULL)) {
 return;
@@ -2024,7 +2020,7 @@ static void test_mode_reboot(void)
 g_autofree char *uri = g_strdup_printf("file:%s/%s", tmpfs,
FILE_TEST_FILENAME);
 MigrateCommon args = {
-.start.use_shmem = true,
+.start.use_memfile = true,
 .connect_uri = uri,
 .listen_uri = "defer",
 .start_hook = test_mode_reboot_start
-- 
2.43.0




[PATCH v2 0/4] tests/qtest/migration-test: Improve shared

2024-05-30 Thread Nicholas Piggin
These apply on top of the previous ppc series. They are similar
to what was discussed except the end result does not attempt to
run /dev/shm tests on Gitlab CI because of concerns about
consistency of test results if shm becomes exhausted.

Thanks,
Nick

Nicholas Piggin (4):
  tests/qtest/migration-test: Use regular file file for shared-memory
tests
  tests/qtest/migration-test: Enable test_mode_reboot
  tests/qtest/migration-test: Fix and enable test_ignore_shared
  tests/qtest/migration-test: Add a postcopy memfile test

 tests/qtest/migration-test.c | 128 ---
 1 file changed, 88 insertions(+), 40 deletions(-)

-- 
2.43.0




Re: [PATCH v3 3/3] target/ppc: handle vcpu hotplug failure gracefully

2024-05-30 Thread Nicholas Piggin
On Thu May 23, 2024 at 5:26 PM AEST, Harsh Prateek Bora wrote:
> On ppc64, the PowerVM hypervisor runs with limited memory and a VCPU
> creation during hotplug may fail during kvm_ioctl for KVM_CREATE_VCPU,
> leading to termination of guest since errp is set to _fatal while
> calling kvm_init_vcpu. This unexpected behaviour can be avoided by
> pre-creating and parking vcpu on success or return error otherwise.
> This enables graceful error delivery for any vcpu hotplug failures while
> the guest can keep running.
>
> Also introducing KVM AccelCPUClass to init cpu_target_realize for kvm.
>
> Tested OK by repeatedly doing a hotplug/unplug of vcpus as below:
>
>  #virsh setvcpus hotplug 40
>  #virsh setvcpus hotplug 70
> error: internal error: unable to execute QEMU command 'device_add':
> kvmppc_cpu_realize: vcpu hotplug failed with -12
>
> Reported-by: Anushree Mathur 
> Suggested-by: Shivaprasad G Bhat 
> Suggested-by: Vaibhav Jain 
> Signed-off by: Harsh Prateek Bora 
> Tested-by: Anushree Mathur 
> ---
>  target/ppc/kvm.c | 41 +
>  1 file changed, 41 insertions(+)
>
> diff --git a/target/ppc/kvm.c b/target/ppc/kvm.c
> index 63930d4a77..8e5a7c3d2d 100644
> --- a/target/ppc/kvm.c
> +++ b/target/ppc/kvm.c
> @@ -48,6 +48,8 @@
>  #include "qemu/mmap-alloc.h"
>  #include "elf.h"
>  #include "sysemu/kvm_int.h"
> +#include "accel/kvm/kvm-cpus.h"
> +#include "hw/core/accel-cpu.h"
>  
>  #define PROC_DEVTREE_CPU  "/proc/device-tree/cpus/"
>  
> @@ -2339,6 +2341,25 @@ static void alter_insns(uint64_t *word, uint64_t 
> flags, bool on)
>  }
>  }
>  
> +static bool kvmppc_cpu_realize(CPUState *cs, Error **errp)
> +{
> +int ret;
> +const char *vcpu_str = (cs->parent_obj.hotplugged == true) ?
> +   "hotplug" : "create";
> +cs->cpu_index = cpu_get_free_index();
> +
> +POWERPC_CPU(cs)->vcpu_id = cs->cpu_index;
> +
> +/* create and park to fail gracefully in case vcpu hotplug fails */

The only thing that wasn't immediately clear to me is that in the
machine init path, this results in qemu termination, and in the
hotplug path it results in graceful hotplug failure. That is the
behaviour we want, maybe just expand the comment slightly to be
more explicit about it. E.g.,

> +ret = kvm_create_and_park_vcpu(cs);
> +if (ret) {
   /*
* This causes QEMU to terminate if initial CPU creation
* fails, and CPU hotplug failure if the error happens
    * there.
*/
> +error_setg(errp, "%s: vcpu %s failed with %d",
> + __func__, vcpu_str, ret);
> +return false;
> +}
> +return true;
> +}
> +

Otherwise looks good.

Reviewed-by: Nicholas Piggin 

>  static void kvmppc_host_cpu_class_init(ObjectClass *oc, void *data)
>  {
>  PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
> @@ -2959,3 +2980,23 @@ void kvmppc_set_reg_tb_offset(PowerPCCPU *cpu, int64_t 
> tb_offset)
>  void kvm_arch_accel_class_init(ObjectClass *oc)
>  {
>  }
> +
> +static void kvm_cpu_accel_class_init(ObjectClass *oc, void *data)
> +{
> +AccelCPUClass *acc = ACCEL_CPU_CLASS(oc);
> +
> +acc->cpu_target_realize = kvmppc_cpu_realize;
> +}
> +
> +static const TypeInfo kvm_cpu_accel_type_info = {
> +.name = ACCEL_CPU_NAME("kvm"),
> +
> +.parent = TYPE_ACCEL_CPU,
> +.class_init = kvm_cpu_accel_class_init,
> +.abstract = true,
> +};
> +static void kvm_cpu_accel_register_types(void)
> +{
> +type_register_static(_cpu_accel_type_info);
> +}
> +type_init(kvm_cpu_accel_register_types);




Re: [PATCH v3 2/3] cpu-common.c: export cpu_get_free_index to be reused later

2024-05-30 Thread Nicholas Piggin
On Thu May 23, 2024 at 5:26 PM AEST, Harsh Prateek Bora wrote:
> This helper provides an easy way to identify the next available free cpu
> index which can be used for vcpu creation. Until now, this is being
> called at a very later stage and there is a need to be able to call it
> earlier (for now, with ppc64) hence the need to export.
>

Reviewed-by: Nicholas Piggin 

> Suggested-by: Nicholas Piggin 
> Signed-off-by: Harsh Prateek Bora 
> ---
>  include/exec/cpu-common.h | 2 ++
>  cpu-common.c  | 7 ---
>  2 files changed, 6 insertions(+), 3 deletions(-)
>
> diff --git a/include/exec/cpu-common.h b/include/exec/cpu-common.h
> index 6d5318895a..0386f1ab29 100644
> --- a/include/exec/cpu-common.h
> +++ b/include/exec/cpu-common.h
> @@ -29,6 +29,8 @@ void cpu_list_lock(void);
>  void cpu_list_unlock(void);
>  unsigned int cpu_list_generation_id_get(void);
>  
> +int cpu_get_free_index(void);
> +
>  void tcg_iommu_init_notifier_list(CPUState *cpu);
>  void tcg_iommu_free_notifier_list(CPUState *cpu);
>  
> diff --git a/cpu-common.c b/cpu-common.c
> index ce78273af5..82bd1b432d 100644
> --- a/cpu-common.c
> +++ b/cpu-common.c
> @@ -57,14 +57,12 @@ void cpu_list_unlock(void)
>  qemu_mutex_unlock(_cpu_list_lock);
>  }
>  
> -static bool cpu_index_auto_assigned;
>  
> -static int cpu_get_free_index(void)
> +int cpu_get_free_index(void)
>  {
>  CPUState *some_cpu;
>  int max_cpu_index = 0;
>  
> -cpu_index_auto_assigned = true;
>  CPU_FOREACH(some_cpu) {
>  if (some_cpu->cpu_index >= max_cpu_index) {
>  max_cpu_index = some_cpu->cpu_index + 1;
> @@ -83,8 +81,11 @@ unsigned int cpu_list_generation_id_get(void)
>  
>  void cpu_list_add(CPUState *cpu)
>  {
> +static bool cpu_index_auto_assigned;
> +
>  QEMU_LOCK_GUARD(_cpu_list_lock);
>  if (cpu->cpu_index == UNASSIGNED_CPU_INDEX) {
> +cpu_index_auto_assigned = true;
>  cpu->cpu_index = cpu_get_free_index();
>  assert(cpu->cpu_index != UNASSIGNED_CPU_INDEX);
>  } else {




Re: [PATCH v3 1/3] accel/kvm: Introduce kvm_create_and_park_vcpu() helper

2024-05-30 Thread Nicholas Piggin
On Thu May 23, 2024 at 5:26 PM AEST, Harsh Prateek Bora wrote:
> There are distinct helpers for creating and parking a KVM vCPU.
> However, there can be cases where a platform needs to create and
> immediately park the vCPU during early stages of vcpu init which
> can later be reused when vcpu thread gets initialized. This would
> help detect failures with kvm_create_vcpu at an early stage.
>
> Based on api refactoring to create/park vcpus introduced in 1/8 of patch 
> series:
> https://lore.kernel.org/qemu-devel/2024052221.232114-1-salil.me...@huawei.com/
>

Reviewed-by: Nicholas Piggin 

> Suggested-by: Nicholas Piggin 
> Signed-off-by: Harsh Prateek Bora 
> ---
>  accel/kvm/kvm-cpus.h |  8 
>  accel/kvm/kvm-all.c  | 12 
>  2 files changed, 20 insertions(+)
>
> diff --git a/accel/kvm/kvm-cpus.h b/accel/kvm/kvm-cpus.h
> index 2e6bb38b5d..00e534b3b9 100644
> --- a/accel/kvm/kvm-cpus.h
> +++ b/accel/kvm/kvm-cpus.h
> @@ -46,4 +46,12 @@ void kvm_park_vcpu(CPUState *cpu);
>   * @returns: KVM fd
>   */
>  int kvm_unpark_vcpu(KVMState *s, unsigned long vcpu_id);
> +
> +/**
> + *  * kvm_create_and_park_vcpu - Create and park a KVM vCPU
> + *   * @cpu: QOM CPUState object for which KVM vCPU has to be created and 
> parked.
> + **
> + * * @returns: 0 when success, errno (<0) when failed.
> + *  */

Something went wrong with re-flowing the comment?

Don't worry about resending for that just now, at least until we work
out the dependency with Salil's series and ready to merge.

Thanks,
Nick

> +int kvm_create_and_park_vcpu(CPUState *cpu);
>  #endif /* KVM_CPUS_H */
> diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c
> index fc30e5d5b8..d70ca62ff5 100644
> --- a/accel/kvm/kvm-all.c
> +++ b/accel/kvm/kvm-all.c
> @@ -398,6 +398,18 @@ int kvm_create_vcpu(CPUState *cpu)
>  return 0;
>  }
>  
> +int kvm_create_and_park_vcpu(CPUState *cpu)
> +{
> +int ret = 0;
> +
> +ret = kvm_create_vcpu(cpu);
> +if (!ret) {
> +kvm_park_vcpu(cpu);
> +}
> +
> +return ret;
> +}
> +
>  static int do_kvm_destroy_vcpu(CPUState *cpu)
>  {
>  KVMState *s = kvm_state;




[PATCH v3 0/4] tests/qtest/migration-test: Improve and enable on ppc64

2024-05-30 Thread Nicholas Piggin
Since v2:
- Fixed subject typo noticed by Thomas.
- Drop the non-ppc patches from the series.

Thanks,
Nick

Nicholas Piggin (4):
  tests/qtest: Move common define from libqos-spapr.h to new ppc-util.h
  tests/qtest/migration-test: Quieten ppc64 QEMU warnings
  tests/qtest/migration-test: Enable on ppc64 TCG
  tests/qtest/migration-test: Use custom asm bios for ppc64

 tests/migration/migration-test.h   |  1 +
 tests/migration/ppc64/a-b-kernel.h | 42 +++
 tests/qtest/libqos/libqos-spapr.h  |  7 
 tests/qtest/ppc-util.h | 19 +
 tests/qtest/boot-serial-test.c |  2 +-
 tests/qtest/migration-test.c   | 53 +---
 tests/qtest/prom-env-test.c|  2 +-
 tests/qtest/pxe-test.c |  2 +-
 tests/migration/Makefile   |  2 +-
 tests/migration/ppc64/Makefile | 15 +++
 tests/migration/ppc64/a-b-kernel.S | 66 ++
 11 files changed, 157 insertions(+), 54 deletions(-)
 create mode 100644 tests/migration/ppc64/a-b-kernel.h
 create mode 100644 tests/qtest/ppc-util.h
 create mode 100644 tests/migration/ppc64/Makefile
 create mode 100644 tests/migration/ppc64/a-b-kernel.S

-- 
2.43.0




[PATCH v3 3/4] tests/qtest/migration-test: Enable on ppc64 TCG

2024-05-30 Thread Nicholas Piggin
ppc64 with TCG seems to no longer be failing this test, perhaps since
commit 03bfc2188f061 ("physmem: Fix migration dirty bitmap coherency
with TCG memory access") which is not ppc specific but was seen to hit
ppc64 quite easily.

Let's enable it again.

The s390x problem has been identified so mention it while we are
adjusting the comment.

Reviewed-by: Thomas Huth 
Signed-off-by: Nicholas Piggin 
---
 tests/qtest/migration-test.c | 16 +++-
 1 file changed, 3 insertions(+), 13 deletions(-)

diff --git a/tests/qtest/migration-test.c b/tests/qtest/migration-test.c
index 48f59822f4..ef9ddef1c8 100644
--- a/tests/qtest/migration-test.c
+++ b/tests/qtest/migration-test.c
@@ -3454,19 +3454,9 @@ int main(int argc, char **argv)
 #endif
 
 /*
- * On ppc64, the test only works with kvm-hv, but not with kvm-pr and TCG
- * is touchy due to race conditions on dirty bits (especially on PPC for
- * some reason)
- */
-if (g_str_equal(arch, "ppc64") &&
-(!has_kvm || access("/sys/module/kvm_hv", F_OK))) {
-g_test_message("Skipping tests: kvm_hv not available");
-goto test_add_done;
-}
-
-/*
- * Similar to ppc64, s390x seems to be touchy with TCG, so disable it
- * there until the problems are resolved
+ * On s390x with TCG, migration is observed to hang due to the 'pending'
+ * state of the flic interrupt controller not being migrated or
+ * reconstructed post-migration. Disable it until the problem is resolved.
  */
 if (g_str_equal(arch, "s390x") && !has_kvm) {
 g_test_message("Skipping tests: s390x host with KVM is required");
-- 
2.43.0




[PATCH v3 2/4] tests/qtest/migration-test: Quieten ppc64 QEMU warnings

2024-05-30 Thread Nicholas Piggin
Reviewed-by: Thomas Huth 
Signed-off-by: Nicholas Piggin 
---
 tests/qtest/migration-test.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/tests/qtest/migration-test.c b/tests/qtest/migration-test.c
index b7e3406471..48f59822f4 100644
--- a/tests/qtest/migration-test.c
+++ b/tests/qtest/migration-test.c
@@ -21,6 +21,7 @@
 #include "chardev/char.h"
 #include "crypto/tlscredspsk.h"
 #include "qapi/qmp/qlist.h"
+#include "ppc-util.h"
 
 #include "migration-helpers.h"
 #include "tests/migration/migration-test.h"
@@ -742,7 +743,8 @@ static int test_migrate_start(QTestState **from, QTestState 
**to,
   "until'", end_address, start_address);
 machine_alias = "pseries";
 machine_opts = "vsmt=8";
-arch_opts = g_strdup("-nodefaults");
+arch_opts = g_strdup("-nodefaults "
+ "-machine " PSERIES_DEFAULT_CAPABILITIES);
 } else if (strcmp(arch, "aarch64") == 0) {
 memory_size = "150M";
 machine_alias = "virt";
-- 
2.43.0




[PATCH v3 4/4] tests/qtest/migration-test: Use custom asm bios for ppc64

2024-05-30 Thread Nicholas Piggin
Similar to other archs, build a custom bios memory updater. Running the
test with OF code is a cool trick, but SLOF takes a long time to boot.
This reduces test time by around 3x (150s to 50s).

Reviewed-by: Fabiano Rosas 
Signed-off-by: Nicholas Piggin 
---
 tests/migration/migration-test.h   |  1 +
 tests/migration/ppc64/a-b-kernel.h | 42 +++
 tests/qtest/migration-test.c   | 37 +++--
 tests/migration/Makefile   |  2 +-
 tests/migration/ppc64/Makefile | 15 +++
 tests/migration/ppc64/a-b-kernel.S | 66 ++
 6 files changed, 131 insertions(+), 32 deletions(-)
 create mode 100644 tests/migration/ppc64/a-b-kernel.h
 create mode 100644 tests/migration/ppc64/Makefile
 create mode 100644 tests/migration/ppc64/a-b-kernel.S

diff --git a/tests/migration/migration-test.h b/tests/migration/migration-test.h
index 68512c0b1b..194df7df6f 100644
--- a/tests/migration/migration-test.h
+++ b/tests/migration/migration-test.h
@@ -22,6 +22,7 @@
 /* PPC */
 #define PPC_TEST_MEM_START (1 * 1024 * 1024)
 #define PPC_TEST_MEM_END   (100 * 1024 * 1024)
+#define PPC_H_PUT_TERM_CHAR 0x58
 
 /* ARM */
 #define ARM_TEST_MEM_START (0x4000 + 1 * 1024 * 1024)
diff --git a/tests/migration/ppc64/a-b-kernel.h 
b/tests/migration/ppc64/a-b-kernel.h
new file mode 100644
index 00..673317efdb
--- /dev/null
+++ b/tests/migration/ppc64/a-b-kernel.h
@@ -0,0 +1,42 @@
+/* This file is automatically generated from the assembly file in
+ * tests/migration/ppc64. 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 ppc64_kernel[] = {
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x7d, 0x20, 0x00, 0xa6, 0x39, 0x40, 0xff, 0xff,
+  0x79, 0x49, 0xf8, 0x0e, 0x7d, 0x20, 0x01, 0x64, 0x3e, 0x80, 0x00, 0x10,
+  0x62, 0x94, 0x00, 0x00, 0x3d, 0x20, 0x06, 0x40, 0x61, 0x29, 0x00, 0x00,
+  0x7e, 0xb4, 0x48, 0x50, 0x39, 0x40, 0x10, 0x00, 0x7e, 0xb5, 0x53, 0xd2,
+  0x38, 0x60, 0x00, 0x58, 0x38, 0x80, 0x00, 0x00, 0x38, 0xa0, 0x00, 0x01,
+  0x38, 0xc0, 0x00, 0x41, 0x78, 0xc6, 0xc1, 0xc6, 0x44, 0x00, 0x00, 0x22,
+  0x38, 0x60, 0x00, 0x00, 0x7e, 0x89, 0xa3, 0x78, 0x7e, 0xa9, 0x03, 0xa6,
+  0x98, 0x69, 0x00, 0x00, 0x39, 0x29, 0x10, 0x00, 0x42, 0x00, 0xff, 0xf8,
+  0x7e, 0x89, 0xa3, 0x78, 0x7e, 0xa9, 0x03, 0xa6, 0x88, 0x69, 0x00, 0x00,
+  0x38, 0x63, 0x00, 0x01, 0x98, 0x69, 0x00, 0x00, 0x39, 0x29, 0x10, 0x00,
+  0x42, 0x00, 0xff, 0xf0, 0x38, 0x60, 0x00, 0x58, 0x38, 0x80, 0x00, 0x00,
+  0x38, 0xa0, 0x00, 0x01, 0x38, 0xc0, 0x00, 0x42, 0x78, 0xc6, 0xc1, 0xc6,
+  0x44, 0x00, 0x00, 0x22, 0x4b, 0xff, 0xff, 0xcc
+};
+
diff --git a/tests/qtest/migration-test.c b/tests/qtest/migration-test.c
index ef9ddef1c8..d6f5ceed80 100644
--- a/tests/qtest/migration-test.c
+++ b/tests/qtest/migration-test.c
@@ -128,6 +128,7 @@ static char *bootpath;
  */
 #include "tests/migration/i386/a-b-bootblock.h"
 #include "tests/migration/aarch64/a-b-kernel.h"
+#include "tests/migration/ppc64/a-b-kernel.h"
 #include "tests/migration/s390x/a-b-bios.h"
 
 static void bootfile_create(char *dir, bool suspend_me)
@@ -147,10 +148,8 @@ static void bootfile_create(char *dir, bool suspend_me)
 content = s390x_elf;
 len = sizeof(s390x_elf);
 } else if (strcmp(arch, "ppc64&q

[PATCH v3 1/4] tests/qtest: Move common define from libqos-spapr.h to new ppc-util.h

2024-05-30 Thread Nicholas Piggin
The spapr QEMU machine defaults is useful outside libqos, so create a
new header for ppc specific qtests and move it there.

Reviewed-by: Thomas Huth 
Signed-off-by: Nicholas Piggin 
---
 tests/qtest/libqos/libqos-spapr.h |  7 ---
 tests/qtest/ppc-util.h| 19 +++
 tests/qtest/boot-serial-test.c|  2 +-
 tests/qtest/prom-env-test.c   |  2 +-
 tests/qtest/pxe-test.c|  2 +-
 5 files changed, 22 insertions(+), 10 deletions(-)
 create mode 100644 tests/qtest/ppc-util.h

diff --git a/tests/qtest/libqos/libqos-spapr.h 
b/tests/qtest/libqos/libqos-spapr.h
index e4483c14f8..a446276416 100644
--- a/tests/qtest/libqos/libqos-spapr.h
+++ b/tests/qtest/libqos/libqos-spapr.h
@@ -9,11 +9,4 @@ QOSState *qtest_spapr_boot(const char *cmdline_fmt, ...)
 G_GNUC_PRINTF(1, 2);
 void qtest_spapr_shutdown(QOSState *qs);
 
-/* List of capabilities needed to silence warnings with TCG */
-#define PSERIES_DEFAULT_CAPABILITIES \
-"cap-cfpc=broken,"   \
-"cap-sbbc=broken,"   \
-"cap-ibs=broken,"\
-"cap-ccf-assist=off,"
-
 #endif
diff --git a/tests/qtest/ppc-util.h b/tests/qtest/ppc-util.h
new file mode 100644
index 00..f68ee93520
--- /dev/null
+++ b/tests/qtest/ppc-util.h
@@ -0,0 +1,19 @@
+/*
+ * PowerPC misc useful things
+ *
+ * Copyright (c) 2024, IBM Corporation.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#ifndef PPC_UTIL_H
+#define PPC_UTIL_H
+
+/* List of capabilities needed to silence warnings with TCG */
+#define PSERIES_DEFAULT_CAPABILITIES \
+"cap-cfpc=broken,"   \
+"cap-sbbc=broken,"   \
+"cap-ibs=broken,"\
+"cap-ccf-assist=off,"
+
+#endif /* PPC_UTIL_H */
diff --git a/tests/qtest/boot-serial-test.c b/tests/qtest/boot-serial-test.c
index df389adeeb..3b92fa5d50 100644
--- a/tests/qtest/boot-serial-test.c
+++ b/tests/qtest/boot-serial-test.c
@@ -15,7 +15,7 @@
 
 #include "qemu/osdep.h"
 #include "libqtest.h"
-#include "libqos/libqos-spapr.h"
+#include "ppc-util.h"
 
 static const uint8_t bios_avr[] = {
 0x88, 0xe0, /* ldi r24, 0x08   */
diff --git a/tests/qtest/prom-env-test.c b/tests/qtest/prom-env-test.c
index 39ccb59797..14705105ad 100644
--- a/tests/qtest/prom-env-test.c
+++ b/tests/qtest/prom-env-test.c
@@ -21,7 +21,7 @@
 
 #include "qemu/osdep.h"
 #include "libqtest.h"
-#include "libqos/libqos-spapr.h"
+#include "ppc-util.h"
 
 #define MAGIC   0xcafec0de
 #define ADDRESS 0x4000
diff --git a/tests/qtest/pxe-test.c b/tests/qtest/pxe-test.c
index e4b48225a5..a3f900fbea 100644
--- a/tests/qtest/pxe-test.c
+++ b/tests/qtest/pxe-test.c
@@ -16,7 +16,7 @@
 #include 
 #include "libqtest.h"
 #include "boot-sector.h"
-#include "libqos/libqos-spapr.h"
+#include "ppc-util.h"
 
 #define NETNAME "net0"
 
-- 
2.43.0




Re: [PATCH] tests/qtest/migrate-test: Add a postcopy memfile test

2024-05-30 Thread Nicholas Piggin
On Thu May 30, 2024 at 3:35 AM AEST, Fabiano Rosas wrote:
> Peter Xu  writes:
>
> > On Wed, May 29, 2024 at 09:54:30AM -0300, Fabiano Rosas wrote:
> >> Nicholas Piggin  writes:
> >> 
> >> > Postcopy requires userfaultfd support, which requires tmpfs if a memory
> >> > file is used.
> >> >
> >> > This adds back support for /dev/shm memory files, but adds preallocation
> >> > to skip environments where that mount is limited in size.
> >> >
> >> > Signed-off-by: Nicholas Piggin 
> >> > ---
> >> >
> >> > How about this? This goes on top of the reset of the patches
> >> > (I'll re-send them all as a series if we can get to some agreement).
> >> >
> >> > This adds back the /dev/shm option with preallocation and adds a test
> >> > case that requires tmpfs.
> >> 
> >> Peter has stronger opinions on this than I do. I'll leave it to him to
> >> decide.
> >
> > Sorry if I gave that feeling; it's more of a stronger willingness to at
> > some point enable shmem for QEMU migration, rather than wanting to push
> > back what Nicholas was trying to do.
>
> Of course, I didn't mean to imply that. I just saying that using /tmp
> would have been fine with me and I don't want to get in the way.
>
> > Enabling more arch for migration
> > tests is definitely worthwhile on its own.
> >
> > Shmem is just some blank spot that IMHO we should start to think about
> > better coverarge. E.g. it is the only sane way to boot the VM that is able
> > to do fast qemu upgrades using ignore-shared, that was true even before
> > Steve's cpr-exec work, which would be much easier than anonymous. And it's
> > also possible shmem can be (in the next 3-5 years) the 1G page provider to
> > replace hugetlb for postcopy's sake - this one is far beyond our current
> > discussion so I won't extend..
>
> Interesting, good to know.
>
> >
> > IMHO shmem should just be a major backend just like anonymous, and the only
> > possible file backend we can test in CI - as hugetlb is harder to manage
> > there.
> >
> >> 
> >> Just note that now we're making the CI less deterministic in relation to
> >> the migration tests. When a test that uses shmem fails, we'll not be
> >> able to consistently reproduce because the test might not even run
> >> depending on what has consumed the shmem first.
> >> 
> >> Let's also take care that the other consumers of shmem (I think just
> >> ivshmem-test) are able to cope with the migration-test taking all the
> >> space, otherwise the CI will still break.
> >
> > Looks like ivshmem-test only uses 1MB shmem constantly so probably that
> > will succeed if the migration test will, but true they face the same
> > challenge and they interfere with each other..  that test sidently pass
> > (instead of skip) if mktempshm() fails.  I guess we don't have a way to
> > solidly test shmem as shmem simply may not be around.
>
> Here we have each of the 5 migration archs taking up some amount of
> memory + each of the 3 supported arches for ivshmem. They all could be
> running in parallel through make check. In practice there's maybe less
> overlap due to timing and not all CI jobs building all archs, but still.

I could just add back the GITLAB_CI gate for shm tests for now then.
>
> >
> > For this patch alone personally I'd avoid using "use_uffd_memfile" as the
> > name, as that's definitely confusing, since shmem can be tested in other
> > setups too without uffd.  Nicolas, please feel free to move ahead with your

I was just thinking uffd could be used with another memfile (hugetlbfs)
but on second thoughts that's a bit silly. So use_shm_memfile would be
better.

> > arch enablement series with /tmp if you want to separate the shmem issue.
>
> Or just leave ignore_shared untouched for the ppc series.

Good idea, I think everybody is happy enough with ppc series so I
will send that first.

Thanks,
Nick



Re: [RFC PATCH 09/10] ppc/pnv: Implement POWER10 PC xscom registers for direct controls

2024-05-30 Thread Nicholas Piggin
On Wed May 29, 2024 at 5:00 PM AEST, Cédric Le Goater wrote:
> On 5/26/24 14:26, Nicholas Piggin wrote:
> > The PC unit in the processor core contains xscom registers that provide
> > low level status and control of the CPU.
> > 
> > This implements "direct controls" sufficient for OPAL (skiboot) firmware
> > use, which is to stop threads and send them non-maskable IPIs in the
> > form of SRESET interrupts.
> > 
> > POWER10 is sufficiently different (particularly QME and special wakeup)
> > from POWER9 that it is not trivial to implement by reusing the code.
> > 
> > Signed-off-by: Nicholas Piggin 
> > ---
> >   include/hw/core/cpu.h |  8 
> >   include/hw/ppc/pnv.h  |  2 +
> >   include/hw/ppc/pnv_core.h |  3 ++
> >   hw/ppc/pnv.c  |  7 +++-
> >   hw/ppc/pnv_core.c | 88 ---
> >   system/cpus.c | 10 +
> >   6 files changed, 112 insertions(+), 6 deletions(-)
> > 
> > diff --git a/include/hw/core/cpu.h b/include/hw/core/cpu.h
> > index bb398e8237..52a8fc65cb 100644
> > --- a/include/hw/core/cpu.h
> > +++ b/include/hw/core/cpu.h
> > @@ -974,6 +974,14 @@ void cpu_reset_interrupt(CPUState *cpu, int mask);
> >*/
> >   void cpu_exit(CPUState *cpu);
> >   
> > +/**
> > + * cpu_pause:
> > + * @cpu: The CPU to pause.
> > + *
> > + * Resumes CPU, i.e. puts CPU into stopped state.
> > + */
> > +void cpu_pause(CPUState *cpu);
> > +
> >   /**
> >* cpu_resume:
> >* @cpu: The CPU to resume.
> > diff --git a/include/hw/ppc/pnv.h b/include/hw/ppc/pnv.h
> > index 93ecb062b4..bec603f1a8 100644
> > --- a/include/hw/ppc/pnv.h
> > +++ b/include/hw/ppc/pnv.h
> > @@ -111,6 +111,8 @@ PnvChip *pnv_chip_add_phb(PnvChip *chip, PnvPHB *phb);
> >   #define PNV_FDT_ADDR  0x0100
> >   #define PNV_TIMEBASE_FREQ 51200ULL
> >   
> > +void pnv_cpu_do_nmi(CPUState *cs);
> > +
> >   /*
> >* BMC helpers
> >*/
> > diff --git a/include/hw/ppc/pnv_core.h b/include/hw/ppc/pnv_core.h
> > index 39f8f33e6c..9599da15ea 100644
> > --- a/include/hw/ppc/pnv_core.h
> > +++ b/include/hw/ppc/pnv_core.h
> > @@ -109,6 +109,9 @@ OBJECT_DECLARE_TYPE(PnvQuad, PnvQuadClass, PNV_QUAD)
> >   struct PnvQuad {
> >   DeviceState parent_obj;
> >   
> > +bool special_wakeup_done;
> > +bool special_wakeup[4];
> > +
> >   uint32_t quad_id;
> >   MemoryRegion xscom_regs;
> >   MemoryRegion xscom_qme_regs;
> > diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c
> > index 5364c55bbb..765142965f 100644
> > --- a/hw/ppc/pnv.c
> > +++ b/hw/ppc/pnv.c
> > @@ -2700,12 +2700,17 @@ static void pnv_cpu_do_nmi_on_cpu(CPUState *cs, 
> > run_on_cpu_data arg)
> >   }
> >   }
> >   
> > +void pnv_cpu_do_nmi(CPUState *cs)
> > +{
> > +async_run_on_cpu(cs, pnv_cpu_do_nmi_on_cpu, RUN_ON_CPU_NULL);
> > +}
> > +
> >   static void pnv_nmi(NMIState *n, int cpu_index, Error **errp)
> >   {
> >   CPUState *cs;
> >   
> >   CPU_FOREACH(cs) {
> > -async_run_on_cpu(cs, pnv_cpu_do_nmi_on_cpu, RUN_ON_CPU_NULL);
> > +pnv_cpu_do_nmi(cs);
> >   }
> >   }
>
> What about ?
>
> https://lore.kernel.org/qemu-devel/20240424093048.180966-1-...@redhat.com/

I haven't forgotten it. I just didn't put it in the first PR since
there was quite a lot of pnv patches to do so I thought I will collect
most of them for another PR.

Thanks,
Nick



Re: [RFC PATCH 08/10] ppc/pnv: Invert the design for big-core machine modelling

2024-05-30 Thread Nicholas Piggin
On Wed May 29, 2024 at 4:57 PM AEST, Cédric Le Goater wrote:
> On 5/26/24 14:26, Nicholas Piggin wrote:
> > POWER9 and POWER10 machines come in two variants, "big-core" and
> > "small-core".
> > 
> > Big core machines are SMT8 from the software point of view, but in the
> > low level platform topology ("xscom registers and pervasive
> > addressing"), these look more like a pair of small cores ganged
> > together.
> > 
> > Presently, the way this is modelled is to create an SMT8 PnvCore and
> > add special cases to xscom and pervasive for big-core mode. This is
> > becoming too complicated to manage as more of the machine is modelled.
> > The better approach looks like the inverse, which is creating 2xPnvCore
> > ganging them together to look like an SMT8 core in TCG. The TCG SMT code
> > is quite simple to do that, and then the xscom and pervasive modelling
> > does not need to differentiate big and small core modes for the most
> > part.
> > 
> > device-tree building does need a special case to only build one
> > CPU node for each big-core because that's what the firmware expects.
> > And so does a special case workaround in the ChipTOD model.
> > 
> > A big-core machine option is added for powernv9 and 10 machines.
>
> That's another patch.

Okay.

> It is difficult to follow all the changes. I think this patch
> needs further splitting.

Sure.

> > Signed-off-by: Nicholas Piggin 
> > ---
> >   include/hw/ppc/pnv.h |   3 +
> >   include/hw/ppc/pnv_core.h|   8 ++
> >   target/ppc/cpu.h |   4 +-
> >   hw/ppc/pnv.c | 183 ---
> >   hw/ppc/pnv_core.c|  20 +++-
> >   hw/ppc/spapr_cpu_core.c  |   6 +-
> >   target/ppc/misc_helper.c |   6 +-
> >   target/ppc/timebase_helper.c |   9 ++
> >   8 files changed, 197 insertions(+), 42 deletions(-)
> > 
> > diff --git a/include/hw/ppc/pnv.h b/include/hw/ppc/pnv.h
> > index 476b136146..93ecb062b4 100644
> > --- a/include/hw/ppc/pnv.h
> > +++ b/include/hw/ppc/pnv.h
> > @@ -100,6 +100,9 @@ struct PnvMachineState {
> >   PnvPnor  *pnor;
> >   
> >   hwaddr   fw_load_addr;
> > +
> > +bool big_core;
> > +bool big_core_tbst_quirk;
>
> I think the quirk should be introduced in its own patch.

Good idea.

> > @@ -157,6 +157,14 @@ static int pnv_dt_core(PnvChip *chip, PnvCore *pc, 
> > void *fdt)
> >   
> >   pnv_cc->processor_id(chip, pc->hwid, 0, , );
> >   
> > +/* Only one DT node per (big) core */
> > +if (tir != 0) {
> > +g_assert(pc->big_core);
> > +g_assert(tir == 1);
> > +g_assert(pc->hwid & 1);
> > +return -1;
>
> return is -1 but it's not an error. right ?

Not an error just a "no CPU node to insert".

It's a bit ugly. Could return bool for yes/no and take a *offset
maybe?

> > @@ -1088,10 +1119,37 @@ static void pnv_power8_init(MachineState *machine)
> >   
> >   static void pnv_power9_init(MachineState *machine)
> >   {
> > -if (machine->smp.threads > 8) {
> > -error_report("Cannot support more than 8 threads/core "
> > - "on a powernv9/10 machine");
> > -exit(1);
> > +PnvMachineState *pnv = PNV_MACHINE(machine);
> > +
> > +if (pnv->big_core) {
>
> It would be interesting to have a max_smt machine class attribute too.

Yeah, as we talked about in the other thread. Probably helps
reduce code.

> > +if (machine->smp.threads > 8) {
> > +error_report("Cannot support more than 8 threads/core "
> > + "on a powernv9/10  machine");
> > +exit(1);
> > +}
> > +if (machine->smp.threads % 2 == 1) {
>
> is_power_of_2()

It does have that check later in pnv_init(), but I wanted
to be careful that we're dividing by 2 below I think it makes
it more obvious (and big-core can't have 1 thread per big core).

> > @@ -1099,6 +1157,8 @@ static void pnv_power9_init(MachineState *machine)
> >   
> >   static void pnv_power10_init(MachineState *machine)
> >   {
> > +PnvMachineState *pnv = PNV_MACHINE(machine);
> > +pnv->big_core_tbst_quirk = true;
> >   pnv_power9_init(machine);
> >   }
> >   
> > @@ -1169,9 +1229,15 @@ static void pnv_processor_id_p9(PnvChip *chip,
> >   uint32_t core_id, uint32_t thread_

Re: [RFC PATCH 05/10] ppc/pnv: Extend chip_pir class method to TIR as well

2024-05-30 Thread Nicholas Piggin
On Wed May 29, 2024 at 4:30 PM AEST, Cédric Le Goater wrote:
> On 5/29/24 02:24, Nicholas Piggin wrote:
> > On Tue May 28, 2024 at 6:32 PM AEST, Harsh Prateek Bora wrote:
> >>
> >>
> >> On 5/26/24 17:56, Nicholas Piggin wrote:
> >>> The chip_pir chip class method allows the platform to set the PIR
> >>> processor identification register. Extend this to a more general
> >>> ID function which also allows the TIR to be set. This is in
> >>> preparation for "big core", which is a more complicated topology
> >>> of cores and threads.
> >>>
> >>> Signed-off-by: Nicholas Piggin 
> >>> ---
> >>>include/hw/ppc/pnv_chip.h |  3 +-
> >>>hw/ppc/pnv.c  | 61 ---
> >>>hw/ppc/pnv_core.c | 10 ---
> >>>3 files changed, 45 insertions(+), 29 deletions(-)
> >>>
> >>> diff --git a/include/hw/ppc/pnv_chip.h b/include/hw/ppc/pnv_chip.h
> >>> index 8589f3291e..679723926a 100644
> >>> --- a/include/hw/ppc/pnv_chip.h
> >>> +++ b/include/hw/ppc/pnv_chip.h
> >>> @@ -147,7 +147,8 @@ struct PnvChipClass {
> >>>
> >>>DeviceRealize parent_realize;
> >>>
> >>> -uint32_t (*chip_pir)(PnvChip *chip, uint32_t core_id, uint32_t 
> >>> thread_id);
> >>> +void (*processor_id)(PnvChip *chip, uint32_t core_id, uint32_t 
> >>> thread_id,
> >>> + uint32_t *pir, uint32_t *tir);
> >>
> >> Should it be named get_chip_core_thread_regs() ?
> > 
> > Yeah, the name isn't great. It is getting the regs, but the regs are the
> > "pervasive id" used as well... but maybe that's not too relevant here.
> > What about we drop chip_ since we have the chip and no other methods use
> > such prefix, then call it get_thread_pir_tir()?
>
> processor relates to chip and so, processor_id() is not great indeed.
> get_pir_tir() would be enough I think.
>
> What would be good though, since pnv is growing, is to start adding
> documentation to these common helpers.

Okay we'll use that name.

You mean just a comment them in the header? Might as well do that for
new ones at least.

Thanks,
Nick



Re: [RFC PATCH 07/10] target/ppc: Add helpers to check for SMT sibling threads

2024-05-30 Thread Nicholas Piggin
On Wed May 29, 2024 at 4:34 PM AEST, Cédric Le Goater wrote:
> On 5/26/24 14:26, Nicholas Piggin wrote:
> > Add helpers for TCG code to determine if there are SMT siblings
> > sharing per-core and per-lpar registers. This simplifies the
> > callers and makes SMT register topology simpler to modify with
> > later changes.
> > 
> > Signed-off-by: Nicholas Piggin 
> > ---
> >   target/ppc/cpu.h |  7 +++
> >   target/ppc/cpu_init.c|  2 +-
> >   target/ppc/excp_helper.c | 16 +++-
> >   target/ppc/misc_helper.c | 27 ++-
> >   target/ppc/timebase_helper.c | 20 +++-
> >   5 files changed, 28 insertions(+), 44 deletions(-)
> > 
> > diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h
> > index 9a89083932..8fd6ade471 100644
> > --- a/target/ppc/cpu.h
> > +++ b/target/ppc/cpu.h
> > @@ -1406,6 +1406,13 @@ struct CPUArchState {
> >   uint64_t pmu_base_time;
> >   };
> >   
> > +#define PPC_CPU_HAS_CORE_SIBLINGS(cs)   \
> > +(cs->nr_threads > 1)
>
> (cs)->nr_threads
>
> > +
> > +#define PPC_CPU_HAS_LPAR_SIBLINGS(cs)   \
> > +((POWERPC_CPU(cs)->env.flags & POWERPC_FLAG_SMT_1LPAR) &&   \
> > + PPC_CPU_HAS_CORE_SIBLINGS(cs))
> > +
>
> I tend to prefer static inline when things get complex.

Yeah agree it has become too much.

Thanks,
Nick



[PATCH] tests/qtest/migrate-test: Add a postcopy memfile test

2024-05-28 Thread Nicholas Piggin
Postcopy requires userfaultfd support, which requires tmpfs if a memory
file is used.

This adds back support for /dev/shm memory files, but adds preallocation
to skip environments where that mount is limited in size.

Signed-off-by: Nicholas Piggin 
---

How about this? This goes on top of the reset of the patches
(I'll re-send them all as a series if we can get to some agreement).

This adds back the /dev/shm option with preallocation and adds a test
case that requires tmpfs.

Thanks,
Nick

 tests/qtest/migration-test.c | 63 +++-
 1 file changed, 55 insertions(+), 8 deletions(-)

diff --git a/tests/qtest/migration-test.c b/tests/qtest/migration-test.c
index 86eace354e..7fd9bbdc18 100644
--- a/tests/qtest/migration-test.c
+++ b/tests/qtest/migration-test.c
@@ -11,6 +11,7 @@
  */
 
 #include "qemu/osdep.h"
+#include "qemu/cutils.h"
 
 #include "libqtest.h"
 #include "qapi/qmp/qdict.h"
@@ -553,6 +554,7 @@ typedef struct {
  */
 bool hide_stderr;
 bool use_memfile;
+bool use_uffd_memfile;
 /* only launch the target process */
 bool only_target;
 /* Use dirty ring if true; dirty logging otherwise */
@@ -739,7 +741,48 @@ static int test_migrate_start(QTestState **from, 
QTestState **to,
 ignore_stderr = "";
 }
 
-if (args->use_memfile) {
+if (!qtest_has_machine(machine_alias)) {
+g_autofree char *msg = g_strdup_printf("machine %s not supported",
+   machine_alias);
+g_test_skip(msg);
+return -1;
+}
+
+if (args->use_uffd_memfile) {
+#if defined(__NR_userfaultfd) && defined(__linux__)
+int fd;
+uint64_t size;
+
+if (!g_file_test("/dev/shm", G_FILE_TEST_IS_DIR)) {
+g_test_skip("/dev/shm does not exist or is not a directory");
+return -1;
+}
+
+/*
+ * Pre-create and allocate the file here, because /dev/shm/
+ * is known to be limited in size in some places (e.g., Gitlab CI).
+ */
+memfile_path = g_strdup_printf("/dev/shm/qemu-%d", getpid());
+fd = open(memfile_path, O_WRONLY | O_CREAT | O_EXCL, S_IRUSR | 
S_IWUSR);
+if (fd == -1) {
+g_test_skip("/dev/shm file could not be created");
+return -1;
+}
+
+g_assert(qemu_strtosz(memory_size, NULL, ) == 0);
+size += 64*1024; /* QEMU may map a bit more memory for a guard page */
+
+if (fallocate(fd, 0, 0, size) == -1) {
+unlink(memfile_path);
+perror("could not alloc"); exit(1);
+g_test_skip("Could not allocate machine memory in /dev/shm");
+return -1;
+}
+close(fd);
+#else
+g_test_skip("userfaultfd is not supported");
+#endif
+} else if (args->use_memfile) {
 memfile_path = g_strdup_printf("/%s/qemu-%d", tmpfs, getpid());
 memfile_opts = g_strdup_printf(
 "-object memory-backend-file,id=mem0,size=%s"
@@ -751,12 +794,6 @@ static int test_migrate_start(QTestState **from, 
QTestState **to,
 kvm_opts = ",dirty-ring-size=4096";
 }
 
-if (!qtest_has_machine(machine_alias)) {
-g_autofree char *msg = g_strdup_printf("machine %s not supported", 
machine_alias);
-g_test_skip(msg);
-return -1;
-}
-
 machine = resolve_machine_version(machine_alias, QEMU_ENV_SRC,
   QEMU_ENV_DST);
 
@@ -807,7 +844,7 @@ static int test_migrate_start(QTestState **from, QTestState 
**to,
  * Remove shmem file immediately to avoid memory leak in test failed case.
  * It's valid because QEMU has already opened this file
  */
-if (args->use_memfile) {
+if (args->use_memfile || args->use_uffd_memfile) {
 unlink(memfile_path);
 }
 
@@ -1275,6 +1312,15 @@ static void test_postcopy(void)
 test_postcopy_common();
 }
 
+static void test_postcopy_memfile(void)
+{
+MigrateCommon args = {
+.start.use_uffd_memfile = true,
+};
+
+test_postcopy_common();
+}
+
 static void test_postcopy_suspend(void)
 {
 MigrateCommon args = {
@@ -3441,6 +3487,7 @@ int main(int argc, char **argv)
 
 if (has_uffd) {
 migration_test_add("/migration/postcopy/plain", test_postcopy);
+migration_test_add("/migration/postcopy/memfile", 
test_postcopy_memfile);
 migration_test_add("/migration/postcopy/recovery/plain",
test_postcopy_recovery);
 migration_test_add("/migration/postcopy/preempt/plain",
-- 
2.43.0




Re: [RFC PATCH 07/10] target/ppc: Add helpers to check for SMT sibling threads

2024-05-28 Thread Nicholas Piggin
On Tue May 28, 2024 at 7:16 PM AEST, Harsh Prateek Bora wrote:
>
>
> On 5/26/24 17:56, Nicholas Piggin wrote:
> > Add helpers for TCG code to determine if there are SMT siblings
> > sharing per-core and per-lpar registers. This simplifies the
> > callers and makes SMT register topology simpler to modify with
> > later changes.
> > 
> > Signed-off-by: Nicholas Piggin 
> > ---
> >   target/ppc/cpu.h |  7 +++
> >   target/ppc/cpu_init.c|  2 +-
> >   target/ppc/excp_helper.c | 16 +++-
> >   target/ppc/misc_helper.c | 27 ++-
> >   target/ppc/timebase_helper.c | 20 +++-
> >   5 files changed, 28 insertions(+), 44 deletions(-)
> > 
> > diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h
> > index 9a89083932..8fd6ade471 100644
> > --- a/target/ppc/cpu.h
> > +++ b/target/ppc/cpu.h
> > @@ -1406,6 +1406,13 @@ struct CPUArchState {
> >   uint64_t pmu_base_time;
> >   };
> >   
> > +#define PPC_CPU_HAS_CORE_SIBLINGS(cs)   \
> > +(cs->nr_threads > 1)
> > +
> > +#define PPC_CPU_HAS_LPAR_SIBLINGS(cs)   \
> > +((POWERPC_CPU(cs)->env.flags & POWERPC_FLAG_SMT_1LPAR) &&   \
> > + PPC_CPU_HAS_CORE_SIBLINGS(cs))
> > +
> >   #define _CORE_ID(cs)\
> >   (POWERPC_CPU(cs)->env.core_index)
> >   
> > diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c
> > index ae483e20c4..e71ee008ed 100644
> > --- a/target/ppc/cpu_init.c
> > +++ b/target/ppc/cpu_init.c
> > @@ -6975,7 +6975,7 @@ static void ppc_cpu_realize(DeviceState *dev, Error 
> > **errp)
> >   
> >   pcc->parent_realize(dev, errp);
> >   
> > -if (env_cpu(env)->nr_threads > 1) {
> > +if (PPC_CPU_HAS_CORE_SIBLINGS(cs)) {
> >   env->flags |= POWERPC_FLAG_SMT;
> >   }
> >   
> > diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c
> > index 0cd542675f..fd45da0f2b 100644
> > --- a/target/ppc/excp_helper.c
> > +++ b/target/ppc/excp_helper.c
> > @@ -3029,7 +3029,7 @@ void helper_book3s_msgsnd(CPUPPCState *env, 
> > target_ulong rb)
> >   brdcast = true;
> >   }
> >   
> > -if (cs->nr_threads == 1 || !brdcast) {
> > +if (!PPC_CPU_HAS_CORE_SIBLINGS(cs) || !brdcast) {
>
> Since there are multiple usage of above macro in negation below as well, 
> we may probably want to introduce another macro PPC_CPU_HAS_SINGLE_CORE

Ah, you mean SINGLE_THREAD. Yes it would read a bit better.

Thanks,
Nick

> which checks only for nr_threads == 1. Anyways,
>
> Reviewed-by: Harsh Prateek Bora 
>
>
> >   ppc_set_irq(cpu, PPC_INTERRUPT_HDOORBELL, 1);
> >   return;
> >   }
> > @@ -3067,21 +3067,19 @@ void helper_book3s_msgsndp(CPUPPCState *env, 
> > target_ulong rb)
> >   CPUState *cs = env_cpu(env);
> >   PowerPCCPU *cpu = env_archcpu(env);
> >   CPUState *ccs;
> > -uint32_t nr_threads = cs->nr_threads;
> >   int ttir = rb & PPC_BITMASK(57, 63);
> >   
> >   helper_hfscr_facility_check(env, HFSCR_MSGP, "msgsndp", 
> > HFSCR_IC_MSGP);
> >   
> > -if (!(env->flags & POWERPC_FLAG_SMT_1LPAR)) {
> > -nr_threads = 1; /* msgsndp behaves as 1-thread in LPAR-per-thread 
> > mode*/
> > -}
> > -
> > -if (!dbell_type_server(rb) || ttir >= nr_threads) {
> > +if (!dbell_type_server(rb)) {
> >   return;
> >   }
> >   
> > -if (nr_threads == 1) {
> > -ppc_set_irq(cpu, PPC_INTERRUPT_DOORBELL, 1);
> > +/* msgsndp behaves as 1-thread in LPAR-per-thread mode*/
> > +if (!PPC_CPU_HAS_LPAR_SIBLINGS(cs)) {
> > +if (ttir == 0) {
> > +ppc_set_irq(cpu, PPC_INTERRUPT_DOORBELL, 1);
> > +}
> >   return;
> >   }
> >   
> > diff --git a/target/ppc/misc_helper.c b/target/ppc/misc_helper.c
> > index 46ba3a5584..598c956cdd 100644
> > --- a/target/ppc/misc_helper.c
> > +++ b/target/ppc/misc_helper.c
> > @@ -49,9 +49,8 @@ void helper_spr_core_write_generic(CPUPPCState *env, 
> > uint32_t sprn,
> >   {
> >   CPUState *cs = env_cpu(env);
> >   CPUState *ccs;
> > -uint32_t nr_threads = cs->nr_threads;
> >   
> > -if (nr_threads == 1) {
> > +if (!PPC_CPU_HAS_CORE_SIBLINGS(cs)) {
> >   env->spr[sprn] = v

Re: [RFC PATCH 06/10] ppc: Add a core_index to CPUPPCState for SMT vCPUs

2024-05-28 Thread Nicholas Piggin
On Tue May 28, 2024 at 6:52 PM AEST, Harsh Prateek Bora wrote:
> corrected typo, it's bitwise.
>
> On 5/28/24 14:18, Harsh Prateek Bora wrote:
> >> -    (POWERPC_CPU(cs)->env.spr_cb[SPR_PIR].default_value & 
> >> ~(cs->nr_threads - 1))
> >> +    (POWERPC_CPU(cs)->env.core_index)
> > 
> > Dont we want to keep the bitwise & with ~(cs->nr_threads - 1) ?
> > How's it taken care ?

For these accessors it actually just wants to have something that
compares if a CPU belongs to the same core or not, so exact value
doesn't really matter.

Maybe the helpers should do that comparison. It could possibly even
be a class method to be really clean, although that's more costly
to call (but writing to a SMT shared register is pretty costly anyway
so maybe doesn't matter).

I'll think a bit more.

Thanks,
Nick



Re: [RFC PATCH 05/10] ppc/pnv: Extend chip_pir class method to TIR as well

2024-05-28 Thread Nicholas Piggin
On Tue May 28, 2024 at 6:32 PM AEST, Harsh Prateek Bora wrote:
>
>
> On 5/26/24 17:56, Nicholas Piggin wrote:
> > The chip_pir chip class method allows the platform to set the PIR
> > processor identification register. Extend this to a more general
> > ID function which also allows the TIR to be set. This is in
> > preparation for "big core", which is a more complicated topology
> > of cores and threads.
> > 
> > Signed-off-by: Nicholas Piggin 
> > ---
> >   include/hw/ppc/pnv_chip.h |  3 +-
> >   hw/ppc/pnv.c  | 61 ---
> >   hw/ppc/pnv_core.c | 10 ---
> >   3 files changed, 45 insertions(+), 29 deletions(-)
> > 
> > diff --git a/include/hw/ppc/pnv_chip.h b/include/hw/ppc/pnv_chip.h
> > index 8589f3291e..679723926a 100644
> > --- a/include/hw/ppc/pnv_chip.h
> > +++ b/include/hw/ppc/pnv_chip.h
> > @@ -147,7 +147,8 @@ struct PnvChipClass {
> >   
> >   DeviceRealize parent_realize;
> >   
> > -uint32_t (*chip_pir)(PnvChip *chip, uint32_t core_id, uint32_t 
> > thread_id);
> > +void (*processor_id)(PnvChip *chip, uint32_t core_id, uint32_t 
> > thread_id,
> > + uint32_t *pir, uint32_t *tir);
>
> Should it be named get_chip_core_thread_regs() ?

Yeah, the name isn't great. It is getting the regs, but the regs are the
"pervasive id" used as well... but maybe that's not too relevant here.
What about we drop chip_ since we have the chip and no other methods use
such prefix, then call it get_thread_pir_tir()?

> > @@ -155,7 +155,7 @@ static int pnv_dt_core(PnvChip *chip, PnvCore *pc, void 
> > *fdt)
> >   char *nodename;
> >   int cpus_offset = get_cpus_node(fdt);
> >   
> > -pir = pnv_cc->chip_pir(chip, pc->hwid, 0);
> > +pnv_cc->processor_id(chip, pc->hwid, 0, , );
>
> As a generic helper API and potentially expandable, it should allow 
> passing NULL for registers whose values are not really sought to avoid 
> having to create un-necessary local variables by the caller.

I'll do that.

Thanks,
Nick



Re: [RFC PATCH 02/10] ppc/pnv: Move timebase state into PnvCore

2024-05-28 Thread Nicholas Piggin
On Tue May 28, 2024 at 5:52 PM AEST, Cédric Le Goater wrote:
> On 5/28/24 08:28, Harsh Prateek Bora wrote:
> > 
> > 
> > On 5/26/24 17:56, Nicholas Piggin wrote:
> >> The timebase state machine is per per-core state and can be driven
> >> by any thread in the core. It is currently implemented as a hack
> >> where the state is in a CPU structure and only thread 0's state is
> >> accessed by the chiptod, which limits programming the timebase
> >> side of the state machine to thread 0 of a core.
> >>
> >> Move the state out into PnvCore and share it among all threads.
> >>
> >> Signed-off-by: Nicholas Piggin 
> >> ---
> >>   include/hw/ppc/pnv_core.h    | 17 
> >>   target/ppc/cpu.h | 20 --
> >>   hw/ppc/pnv_chiptod.c |  6 ++--
> >>   target/ppc/timebase_helper.c | 53 
> >>   4 files changed, 49 insertions(+), 47 deletions(-)
> >>
> >> diff --git a/include/hw/ppc/pnv_core.h b/include/hw/ppc/pnv_core.h
> >> index 30c1e5b1a3..f434c71547 100644
> >> --- a/include/hw/ppc/pnv_core.h
> >> +++ b/include/hw/ppc/pnv_core.h
> >> @@ -25,6 +25,20 @@
> >>   #include "hw/ppc/pnv.h"
> >>   #include "qom/object.h"
> >> +/* ChipTOD and TimeBase State Machine */
> >> +struct pnv_tod_tbst {
> >> +    int tb_ready_for_tod; /* core TB ready to receive TOD from chiptod */
> >> +    int tod_sent_to_tb;   /* chiptod sent TOD to the core TB */
> >> +
> >> +    /*
> >> + * "Timers" for async TBST events are simulated by mfTFAC because TFAC
> >> + * is polled for such events. These are just used to ensure firmware
> >> + * performs the polling at least a few times.
> >> + */
> >> +    int tb_state_timer;
> >> +    int tb_sync_pulse_timer;
> >> +};
> >> +
> >>   #define TYPE_PNV_CORE "powernv-cpu-core"
> >>   OBJECT_DECLARE_TYPE(PnvCore, PnvCoreClass,
> >>   PNV_CORE)
> >> @@ -38,6 +52,9 @@ struct PnvCore {
> >>   uint32_t pir;
> >>   uint32_t hwid;
> >>   uint64_t hrmor;
> >> +
> >> +    struct pnv_tod_tbst pnv_tod_tbst;
> >> +
> > 
> > Now that it is part of struct PnvCore itself, we can drop pnv_ prefix
> > and just call the member variable as tod_tbst ?
>
> yes and rename pnv_tod_tbst using CamelCase please.

Okay will do. That'll look nicer.

Thanks,
Nick



Re: [RFC PATCH 04/10] ppc/pnv: specialise init for powernv8/9/10 machines

2024-05-28 Thread Nicholas Piggin
On Tue May 28, 2024 at 5:45 PM AEST, Cédric Le Goater wrote:
> On 5/28/24 09:10, Harsh Prateek Bora wrote:
> > Hi Nick,
> > 
> > On 5/26/24 17:56, Nicholas Piggin wrote:
> >> This will allow different settings and checks for different
> >> machine types with later changes.
> >>
> >> Signed-off-by: Nicholas Piggin 
> >> ---
> >>   hw/ppc/pnv.c | 35 ++-
> >>   1 file changed, 30 insertions(+), 5 deletions(-)
> >>
> >> diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c
> >> index 6e3a5ccdec..a706de2e36 100644
> >> --- a/hw/ppc/pnv.c
> >> +++ b/hw/ppc/pnv.c
> >> @@ -976,11 +976,6 @@ static void pnv_init(MachineState *machine)
> >>   pnv->num_chips =
> >>   machine->smp.max_cpus / (machine->smp.cores * 
> >> machine->smp.threads);
> >> -    if (machine->smp.threads > 8) {
> >> -    error_report("Cannot support more than 8 threads/core "
> >> - "on a powernv machine");
> >> -    exit(1);
> >> -    }
> >>   if (!is_power_of_2(machine->smp.threads)) {
> >>   error_report("Cannot support %d threads/core on a powernv"
> >>    "machine because it must be a power of 2",
> >> @@ -1076,6 +1071,33 @@ static void pnv_init(MachineState *machine)
> >>   }
> >>   }
> >> +static void pnv_power8_init(MachineState *machine)
> >> +{
> >> +    if (machine->smp.threads > 8) {
> >> +    error_report("Cannot support more than 8 threads/core "
> >> + "on a powernv POWER8 machine");
> > 
> > We could use mc->desc for machine name above, so that ..
> > 
> >> +    exit(1);
> >> +    }
> > 
> > with this patch, we can reuse p8 init for both p9 and p10 (and not just 
> > reuse p9 for p10 with hard coded string?).
>
> Good idea. You could add a 'max_smt' attribute to PnvMachineClass to limit
> POWER8 to one.

Okay I'll see how that goes. Good suggestions.

Thanks,
Nick



Re: [PATCH v4 11/11] ppc/pnv: Update skiboot.lid to support Power11

2024-05-28 Thread Nicholas Piggin
On Tue May 28, 2024 at 5:15 PM AEST, Cédric Le Goater wrote:
> On 5/28/24 09:05, Aditya Gupta wrote:
> > Skiboot/OPAL patches are in discussion upstream [1], with corresponding
> > commits in github repository [2].
> > 
> > Update skiboot.lid, with binary built from 'upstream_power11' branch
> > of skiboot repository with Power11 enablement patches [2].
> > 
> > ---
> > This patch can be skipped for now, if need to wait for patches to be
> > merged in open-power/skiboot. Have updated the skiboot.lid to aid in
> > testing this patch series.
>
> When is the merge in skiboot planned ? QEMU 9.1 freeze is in ~2 months.

I think I will try to get spapr bits in for 9.1, but may just skip pnv
for this round since there's a bunch of other stuff including some pnv
churn I'd like to get in 9.1.

Thanks,
Nick



Re: [RFC PATCH 03/10] target/ppc: Improve SPR indirect registers

2024-05-28 Thread Nicholas Piggin
On Tue May 28, 2024 at 4:50 PM AEST, Harsh Prateek Bora wrote:
>
> Hi Nick,
>
> On 5/26/24 17:56, Nicholas Piggin wrote:
> > SPRC/SPRD were recently added to all BookS CPUs supported, but
> > they are only tested on POWER9 and POWER10, so restrict them to
> > those CPUs.
> > 
>
> Hope you mean to restrict to P9/10 for both spapr and pnv or just pnv ?

For pnv, but they are hypervisor registers so they can not be
accessed with spapr.

[...]

> > @@ -321,11 +322,25 @@ void helper_store_sprc(CPUPPCState *env, target_ulong 
> > val)
> >   
> >   target_ulong helper_load_sprd(CPUPPCState *env)
> >   {
> > +PowerPCCPU *cpu = env_archcpu(env);
> > +PnvCore *pc = pnv_cpu_state(cpu)->core;
>
> We may want to avoid creating local variable cpu here also like previous 
> patches.

Since we have a maze of pointers and types, sometimes I like to
write the types down, but maybe that's just me :P

> However, is this helper meant to be accessible for spapr as well ?

Right, it's not. I *think* it should be okay to do this since it
should never be reached by spapr.

Thanks,
Nick



Re: [PATCH] tests/qtest/migrate-test: Use regular file file for shared-memory tests

2024-05-28 Thread Nicholas Piggin
On Wed May 29, 2024 at 2:05 AM AEST, Peter Xu wrote:
> On Tue, May 28, 2024 at 09:35:22AM -0400, Peter Xu wrote:
> > On Tue, May 28, 2024 at 02:27:57PM +1000, Nicholas Piggin wrote:
> > > There is no need to use /dev/shm for file-backed memory devices, and
> > > it is too small to be usable in gitlab CI. Switch to using a regular
> > > file in /tmp/ which will usually have more space available.
> > > 
> > > Signed-off-by: Nicholas Piggin 
> > > ---
> > > Am I missing something? AFAIKS there is not even any point using
> > > /dev/shm aka tmpfs anyway, there is not much special about it as a
> > > filesystem. This applies on top of the series just sent, and passes
> > > gitlab CI qtests including aarch64.
> > 
> > I think it's just that /dev/shm guarantees shmem usage, while the var
> > "tmpfs" implies g_dir_make_tmp() which may be another non-ram based file
> > system, while that'll be slightly different comparing to what a real user
> > would use - we don't suggest user to put guest RAM on things like btrfs.

Right, these days I think /tmp usually is not tmpfs but just a regular
filesystem. For these tests that's okay though. And it gets us working
with gitlab CI. The ignore-shared test works and is verified to skip the
copy (according to counters and some tracing I did) so I think it's a
good step.

> > 
> > One real implication is if we add a postcopy test it'll fail with
> > g_dir_make_tmp() when it is not pointing to a shmem mount, as
> > UFFDIO_REGISTER will fail there.  But that test doesn't yet exist as the
> > QEMU paths should be the same even if Linux will trigger different paths
> > when different types of mem is used (anonymous v.s. shmem).

Ah okay userfault. I guess that would require real tmpfs. We could just
add a new option to the harness for require_uffd when it comes up?

> > If the goal here is to properly handle the case where tmpfs doesn't have
> > enough space, how about what I suggested in the other email?
> > 
> > https://lore.kernel.org/r/ZlSppKDE6wzjCF--@x1n
> > 
> > IOW, try populate the shmem region before starting the guest, skip if
> > population failed.  Would that work?

I think that's good if you _need_ shm (e.g., for a uffd test), but
we should permit tests that only require a memory file.

Thanks,
Nick



[PATCH 1/2] ppc/pnv: Fix loss of LPC SERIRQ interrupts

2024-05-28 Thread Nicholas Piggin
From: Glenn Miles 

The LPC HC irq status register bits are set when an LPC IRQSER input is
asserted. These irq status bits drive the PSI irq to the CPU interrupt
controller. The LPC HC irq status bits are cleared by software writing
to the register with 1's for the bits to clear.

Existing register write was clearing the irq status bits even when the
input was asserted, this results in interrupts being lost.

This fix changes the behavior to keep track of the device IRQ status
in internal state that is separate from the irq status register, and
only allowing the irq status bits to be cleared if the associated
input is not asserted.

[np: rebased before P9 PSI SERIRQ patch, adjust changelog/comments]
Signed-off-by: Glenn Miles 
Signed-off-by: Nicholas Piggin 
---
 include/hw/ppc/pnv_lpc.h |  3 +++
 hw/ppc/pnv_lpc.c | 22 +++---
 2 files changed, 22 insertions(+), 3 deletions(-)

diff --git a/include/hw/ppc/pnv_lpc.h b/include/hw/ppc/pnv_lpc.h
index 5d22c45570..97c6872c3f 100644
--- a/include/hw/ppc/pnv_lpc.h
+++ b/include/hw/ppc/pnv_lpc.h
@@ -73,6 +73,9 @@ struct PnvLpcController {
 uint32_t opb_irq_pol;
 uint32_t opb_irq_input;
 
+/* LPC device IRQ state */
+uint32_t lpc_hc_irq_inputs;
+
 /* LPC HC registers */
 uint32_t lpc_hc_fw_seg_idsel;
 uint32_t lpc_hc_fw_rd_acc_size;
diff --git a/hw/ppc/pnv_lpc.c b/hw/ppc/pnv_lpc.c
index d692858bee..252690dcaa 100644
--- a/hw/ppc/pnv_lpc.c
+++ b/hw/ppc/pnv_lpc.c
@@ -505,7 +505,14 @@ static void lpc_hc_write(void *opaque, hwaddr addr, 
uint64_t val,
 pnv_lpc_eval_irqs(lpc);
 break;
 case LPC_HC_IRQSTAT:
-lpc->lpc_hc_irqstat &= ~val;
+/*
+ * This register is write-to-clear for the IRQSER (LPC device IRQ)
+ * status. However if the device has not de-asserted its interrupt
+ * that will just raise this IRQ status bit again. Model this by
+ * keeping track of the inputs and only clearing if the inputs are
+ * deasserted.
+ */
+lpc->lpc_hc_irqstat &= ~(val & ~lpc->lpc_hc_irq_inputs);
 pnv_lpc_eval_irqs(lpc);
 break;
 case LPC_HC_ERROR_ADDRESS:
@@ -803,11 +810,20 @@ static void pnv_lpc_isa_irq_handler_cpld(void *opaque, 
int n, int level)
 static void pnv_lpc_isa_irq_handler(void *opaque, int n, int level)
 {
 PnvLpcController *lpc = PNV_LPC(opaque);
+uint32_t irq_bit = LPC_HC_IRQ_SERIRQ0 >> n;
 
-/* The Naples HW latches the 1 levels, clearing is done by SW */
 if (level) {
-lpc->lpc_hc_irqstat |= LPC_HC_IRQ_SERIRQ0 >> n;
+lpc->lpc_hc_irq_inputs |= irq_bit;
+
+/*
+* The LPC HC in Naples and later latches LPC IRQ into a bit field in
+* the IRQSTAT register, and that drives the PSI IRQ to the IC.
+* Software clears this bit manually (see LPC_HC_IRQSTAT handler).
+ */
+lpc->lpc_hc_irqstat |= irq_bit;
 pnv_lpc_eval_irqs(lpc);
+} else {
+lpc->lpc_hc_irq_inputs &= ~irq_bit;
 }
 }
 
-- 
2.43.0




[PATCH 2/2] ppc/pnv: Implement POWER9 LPC PSI serirq outputs and auto-clear function

2024-05-28 Thread Nicholas Piggin
The POWER8 LPC ISA device irqs all get combined and reported to the line
connected the PSI LPCHC irq. POWER9 changed this so only internal LPC
host controller irqs use that line, and the device irqs get routed to
4 new lines connected to PSI SERIRQ0-3.

POWER9 also introduced a new feature that automatically clears the irq
status in the LPC host controller when EOI'ed, so software does not have
to.

The powernv OPAL (skiboot) firmware managed to work because the LPCHC
irq handler scanned all LPC irqs and handled those including clearing
status even on POWER9 systems. So LPC irqs worked despite OPAL thinking
it was running in POWER9 mode. After this change, UART interrupts show
up on serirq1 which is where OPAL routes them to:

 cat /proc/interrupts
 ...
 20:  0  XIVE-IRQ 1048563 Level opal-psi#0:lpchc
 ...
 25: 34  XIVE-IRQ 1048568 Level opal-psi#0:lpc_serirq_mux1

Whereas they previously turn up on lpchc.

Signed-off-by: Nicholas Piggin 
---
Since v1:
- Fix and test power8
- Rebase onto Glenn's fix
- Move irq_to_serirq_route from global into PnvLpcController
- Don't have SERIRQ irqs latch the OPB irq status register, docs don't
  suggest they do and skiboot does not clear that bit for SERIRQ path.
- Have the SERIRQ path use the LPCHC IRQ mask (missed in previous
  patch).

 include/hw/ppc/pnv_lpc.h |  14 -
 hw/ppc/pnv.c |  36 +--
 hw/ppc/pnv_lpc.c | 128 ---
 3 files changed, 148 insertions(+), 30 deletions(-)

diff --git a/include/hw/ppc/pnv_lpc.h b/include/hw/ppc/pnv_lpc.h
index 97c6872c3f..e0fd5e4130 100644
--- a/include/hw/ppc/pnv_lpc.h
+++ b/include/hw/ppc/pnv_lpc.h
@@ -23,6 +23,7 @@
 #include "exec/memory.h"
 #include "hw/ppc/pnv.h"
 #include "hw/qdev-core.h"
+#include "hw/isa/isa.h" /* For ISA_NUM_IRQS */
 
 #define TYPE_PNV_LPC "pnv-lpc"
 typedef struct PnvLpcClass PnvLpcClass;
@@ -87,8 +88,19 @@ struct PnvLpcController {
 /* XSCOM registers */
 MemoryRegion xscom_regs;
 
+/*
+ * In P8, ISA irqs are combined with internal sources to drive the
+ * LPCHC interrupt output. P9 ISA irqs raise one of 4 lines that
+ * drive PSI SERIRQ irqs, routing according to OPB routing registers.
+ */
+bool psi_has_serirq;
+
 /* PSI to generate interrupts */
-qemu_irq psi_irq;
+qemu_irq psi_irq_lpchc;
+
+/* P9 serirq lines and irq routing table */
+qemu_irq psi_irq_serirq[4];
+int irq_to_serirq_route[ISA_NUM_IRQS];
 };
 
 struct PnvLpcClass {
diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c
index 6e3a5ccdec..f6c3e91b3a 100644
--- a/hw/ppc/pnv.c
+++ b/hw/ppc/pnv.c
@@ -728,7 +728,8 @@ static ISABus *pnv_chip_power8_isa_create(PnvChip *chip, 
Error **errp)
 Pnv8Chip *chip8 = PNV8_CHIP(chip);
 qemu_irq irq = qdev_get_gpio_in(DEVICE(>psi), PSIHB_IRQ_EXTERNAL);
 
-qdev_connect_gpio_out(DEVICE(>lpc), 0, irq);
+qdev_connect_gpio_out_named(DEVICE(>lpc), "LPCHC", 0, irq);
+
 return pnv_lpc_isa_create(>lpc, true, errp);
 }
 
@@ -737,25 +738,48 @@ static ISABus *pnv_chip_power8nvl_isa_create(PnvChip 
*chip, Error **errp)
 Pnv8Chip *chip8 = PNV8_CHIP(chip);
 qemu_irq irq = qdev_get_gpio_in(DEVICE(>psi), PSIHB_IRQ_LPC_I2C);
 
-qdev_connect_gpio_out(DEVICE(>lpc), 0, irq);
+qdev_connect_gpio_out_named(DEVICE(>lpc), "LPCHC", 0, irq);
+
 return pnv_lpc_isa_create(>lpc, false, errp);
 }
 
 static ISABus *pnv_chip_power9_isa_create(PnvChip *chip, Error **errp)
 {
 Pnv9Chip *chip9 = PNV9_CHIP(chip);
-qemu_irq irq = qdev_get_gpio_in(DEVICE(>psi), PSIHB9_IRQ_LPCHC);
+qemu_irq irq;
+
+irq = qdev_get_gpio_in(DEVICE(>psi), PSIHB9_IRQ_LPCHC);
+qdev_connect_gpio_out_named(DEVICE(>lpc), "LPCHC", 0, irq);
+
+irq = qdev_get_gpio_in(DEVICE(>psi), PSIHB9_IRQ_LPC_SIRQ0);
+qdev_connect_gpio_out_named(DEVICE(>lpc), "SERIRQ", 0, irq);
+irq = qdev_get_gpio_in(DEVICE(>psi), PSIHB9_IRQ_LPC_SIRQ1);
+qdev_connect_gpio_out_named(DEVICE(>lpc), "SERIRQ", 1, irq);
+irq = qdev_get_gpio_in(DEVICE(>psi), PSIHB9_IRQ_LPC_SIRQ2);
+qdev_connect_gpio_out_named(DEVICE(>lpc), "SERIRQ", 2, irq);
+irq = qdev_get_gpio_in(DEVICE(>psi), PSIHB9_IRQ_LPC_SIRQ3);
+qdev_connect_gpio_out_named(DEVICE(>lpc), "SERIRQ", 3, irq);
 
-qdev_connect_gpio_out(DEVICE(>lpc), 0, irq);
 return pnv_lpc_isa_create(>lpc, false, errp);
 }
 
 static ISABus *pnv_chip_power10_isa_create(PnvChip *chip, Error **errp)
 {
 Pnv10Chip *chip10 = PNV10_CHIP(chip);
-qemu_irq irq = qdev_get_gpio_in(DEVICE(>psi), PSIHB9_IRQ_LPCHC);
+qemu_irq irq;
+
+irq = qdev_get_gpio_in(DEVICE(>psi), PSIHB9_IRQ_LPCHC);
+qdev_connect_gpio_out_named(DEVICE(>lpc), "LPCHC", 0, irq);
+
+irq = qdev_get_gpio_in(DEVICE(>psi), PSIHB9_IRQ_LPC_SIRQ0);
+qdev_connect_gpio_out

[PATCH 0/2] ppc/pnv: LPC interrupt fixes

2024-05-28 Thread Nicholas Piggin
Here is v2 of the POWER9 PSI serirq patch with changes suggested by
Cedric and some other things. But also in front of that we have a fix
from Glenn for a lost interrupt problem.

I rebased Glenn's patch and also changed some comments and changelog
a bit so any bugs or silly comments are probably my fault, but debug
and fix is credit to him.

Thanks,
Nick

Glenn Miles (1):
  ppc/pnv: Fix loss of LPC SERIRQ interrupts

Nicholas Piggin (1):
  ppc/pnv: Implement POWER9 LPC PSI serirq outputs and auto-clear
function

 include/hw/ppc/pnv_lpc.h |  17 -
 hw/ppc/pnv.c |  36 --
 hw/ppc/pnv_lpc.c | 150 ---
 3 files changed, 170 insertions(+), 33 deletions(-)

-- 
2.43.0




[PATCH] tests/qtest/migrate-test: Use regular file file for shared-memory tests

2024-05-27 Thread Nicholas Piggin
There is no need to use /dev/shm for file-backed memory devices, and
it is too small to be usable in gitlab CI. Switch to using a regular
file in /tmp/ which will usually have more space available.

Signed-off-by: Nicholas Piggin 
---
Am I missing something? AFAIKS there is not even any point using
/dev/shm aka tmpfs anyway, there is not much special about it as a
filesystem. This applies on top of the series just sent, and passes
gitlab CI qtests including aarch64.

Thanks,
Nick

 tests/qtest/migration-test.c | 41 
 1 file changed, 13 insertions(+), 28 deletions(-)

diff --git a/tests/qtest/migration-test.c b/tests/qtest/migration-test.c
index 45830eb213..86eace354e 100644
--- a/tests/qtest/migration-test.c
+++ b/tests/qtest/migration-test.c
@@ -552,7 +552,7 @@ typedef struct {
  * unconditionally, because it means the user would like to be verbose.
  */
 bool hide_stderr;
-bool use_shmem;
+bool use_memfile;
 /* only launch the target process */
 bool only_target;
 /* Use dirty ring if true; dirty logging otherwise */
@@ -672,29 +672,14 @@ static int test_migrate_start(QTestState **from, 
QTestState **to,
 g_autofree gchar *cmd_source = NULL;
 g_autofree gchar *cmd_target = NULL;
 const gchar *ignore_stderr;
-g_autofree char *shmem_opts = NULL;
-g_autofree char *shmem_path = NULL;
+g_autofree char *memfile_opts = NULL;
+g_autofree char *memfile_path = NULL;
 const char *kvm_opts = NULL;
 const char *arch = qtest_get_arch();
 const char *memory_size;
 const char *machine_alias, *machine_opts = "";
 g_autofree char *machine = NULL;
 
-if (args->use_shmem) {
-if (!g_file_test("/dev/shm", G_FILE_TEST_IS_DIR)) {
-g_test_skip("/dev/shm is not supported");
-return -1;
-}
-if (getenv("GITLAB_CI")) {
-/*
- * Gitlab runners are limited to 64MB shm size. See:
- * https://lore.kernel.org/all/87ttq5fvh7@suse.de/
- */
-g_test_skip("/dev/shm is not supported in Gitlab CI environment");
-return -1;
-}
-}
-
 dst_state = (QTestMigrationState) { };
 src_state = (QTestMigrationState) { };
 bootfile_create(tmpfs, args->suspend_me);
@@ -754,12 +739,12 @@ static int test_migrate_start(QTestState **from, 
QTestState **to,
 ignore_stderr = "";
 }
 
-if (args->use_shmem) {
-shmem_path = g_strdup_printf("/dev/shm/qemu-%d", getpid());
-shmem_opts = g_strdup_printf(
+if (args->use_memfile) {
+memfile_path = g_strdup_printf("/%s/qemu-%d", tmpfs, getpid());
+memfile_opts = g_strdup_printf(
 "-object memory-backend-file,id=mem0,size=%s"
 ",mem-path=%s,share=on -numa node,memdev=mem0",
-memory_size, shmem_path);
+memory_size, memfile_path);
 }
 
 if (args->use_dirty_ring) {
@@ -788,7 +773,7 @@ static int test_migrate_start(QTestState **from, QTestState 
**to,
  memory_size, tmpfs,
  arch_opts ? arch_opts : "",
  arch_source ? arch_source : "",
- shmem_opts ? shmem_opts : "",
+ memfile_opts ? memfile_opts : "",
  args->opts_source ? args->opts_source : "",
  ignore_stderr);
 if (!args->only_target) {
@@ -810,7 +795,7 @@ static int test_migrate_start(QTestState **from, QTestState 
**to,
  memory_size, tmpfs, uri,
  arch_opts ? arch_opts : "",
  arch_target ? arch_target : "",
- shmem_opts ? shmem_opts : "",
+ memfile_opts ? memfile_opts : "",
  args->opts_target ? args->opts_target : "",
  ignore_stderr);
 *to = qtest_init_with_env(QEMU_ENV_DST, cmd_target);
@@ -822,8 +807,8 @@ static int test_migrate_start(QTestState **from, QTestState 
**to,
  * Remove shmem file immediately to avoid memory leak in test failed case.
  * It's valid because QEMU has already opened this file
  */
-if (args->use_shmem) {
-unlink(shmem_path);
+if (args->use_memfile) {
+unlink(memfile_path);
 }
 
 return 0;
@@ -1875,7 +1860,7 @@ static void test_ignore_shared(void)
 g_autofree char *uri = g_strdup_printf("unix:%s/migsocket", tmpfs);
 QTestState *from, *to;
 MigrateStart args = {
-.use_shmem = true,
+.use_memfile = true,
 };
 
 

Re: TCG change broke MorphOS boot on sam460ex

2024-05-27 Thread Nicholas Piggin
On Tue May 28, 2024 at 8:23 AM AEST, BALATON Zoltan wrote:
> On Wed, 3 Apr 2024, Nicholas Piggin wrote:
> > On Tue Apr 2, 2024 at 9:32 PM AEST, BALATON Zoltan wrote:
> >> On Thu, 21 Mar 2024, BALATON Zoltan wrote:
> >>> On 27/2/24 17:47, BALATON Zoltan wrote:
> >>>> Hello,
> >>>>
> >>>> Commit 18a536f1f8 (accel/tcg: Always require can_do_io) broke booting
> >>>> MorphOS on sam460ex (this was before 8.2.0 and I thought I've verified it
> >>>> before that release but apparently missed it back then). It can be
> >>>> reproduced with https://www.morphos-team.net/morphos-3.18.iso and 
> >>>> following
> >>>> command:
> >>>>
> >>>> qemu-system-ppc -M sam460ex -serial stdio -d unimp,guest_errors \
> >>>>    -drive if=none,id=cd,format=raw,file=morphos-3.18.iso \
> >>>>    -device ide-cd,drive=cd,bus=ide.1
> >>
> >> Any idea on this one? While MorphOS boots on other machines and other OSes
> >> seem to boot on this machine it may still suggest there's some problem
> >> somewhere as this worked before. So it may worth investigating it to make
> >> sure there's no bug that could affect other OSes too even if they boot. I
> >> don't know how to debug this so some help would be needed.
> >
> > In the bad case it crashes after running this TB:
> >
> > 
> > IN:
> > 0x00c01354:  38c00040  li   r6, 0x40
> > 0x00c01358:  38e10204  addi r7, r1, 0x204
> > 0x00c0135c:  39010104  addi r8, r1, 0x104
> > 0x00c01360:  39410004  addi r10, r1, 4
> > 0x00c01364:  3920  li   r9, 0
> > 0x00c01368:  7cc903a6  mtctrr6
> > 0x00c0136c:  84c70004  lwzu r6, 4(r7)
> > 0x00c01370:  7cc907a4  tlbwehi  r6, r9
> > 0x00c01374:  84c80004  lwzu r6, 4(r8)
> > 0x00c01378:  7cc90fa4  tlbwelo  r6, r9
> > 0x00c0137c:  84ca0004  lwzu r6, 4(r10)
> > 0x00c01380:  7cc917a4  tlbwehi  r6, r9
> > 0x00c01384:  39290001  addi r9, r9, 1
> > 0x00c01388:  4200ffe4  bdnz 0xc0136c
> > 
> > IN:
> > 0x00c01374: unable to read memory
> > 
> >
> > "unable to read memory" is the tracer, it does actually translate
> > the address, but it points to a wayward real address which returns
> > 0 to TCG, which is an invalid instruction.
> >
> > The good case instead doesn't exit the TB after 0x00c01370 but after
> > the complete loop at the bdnz. That look like this after the same
> > first TB:
> >
> > 
> > IN:
> > 0x00c0136c:  84c70004  lwzu r6, 4(r7)
> > 0x00c01370:  7cc907a4  tlbwehi  r6, r9
> > 0x00c01374:  84c80004  lwzu r6, 4(r8)
> > 0x00c01378:  7cc90fa4  tlbwelo  r6, r9
> > 0x00c0137c:  84ca0004  lwzu r6, 4(r10)
> > 0x00c01380:  7cc917a4  tlbwehi  r6, r9
> > 0x00c01384:  39290001  addi r9, r9, 1
> > 0x00c01388:  4200ffe4  bdnz 0xc0136c
> > 
> > IN:
> > 0x00c0138c:  4c00012c  isync
> >
> > All the tlbwe are executed in the same TB. MMU tracing shows the
> > first tlbwehi creates a new valid(!) TLB for 0x-0x1
> > that has a garbage RPN because the tlbwelo did not run yet.
> >
> > What's happening in the bad case is that the translator breaks
> > and "re-fetches" instructions in the middle of that sequence, and
> > that's where the bogus translation causes 0 to be returned. The
> > good case the whole block is executed in the same fetch which
> > creates correct translations.
> >
> > So it looks like a morphos bug, the can-do-io change just happens
> > to cause it to re-fetch in that place, but that could happen for
> > a number of reasons, so you can't rely on TLB *only* changing or
> > ifetch *only* re-fetching at a sync point like isync.
> >
> > I would expect code like this to write an invalid entry with tlbwehi,
> > then tlbwelo to set the correct RPN, then make the entry valid with
> > the second tlbwehi. It would probably fix the bug if you just did the
> > first tlbwehi with r6=0 (or at least without the 0x200 bit set).
>
> Revisiting this, I've found in the docs that PPC440 has shadow TLBs so 
> this code can rely upon the TLB not being invalidated until isync and 
> works on real machine but breaks on QEMU.

I never programmed for 440 but it's unclear to me from the docs how
much you can rely on this programatically (you would have to ensure
no page crossings, disable interrupts, hope for no machine check,
etc).

But it does break

[PATCH v2 6/6] tests/qtest/migration-test: Use custom asm bios for ppc64

2024-05-27 Thread Nicholas Piggin
Similar to other archs, build a custom bios memory updater. Running the
test with OF code is a cool trick, but SLOF takes a long time to boot.
This reduces test time by around 3x (150s to 50s).

Reviewed-by: Fabiano Rosas 
Signed-off-by: Nicholas Piggin 
---
 tests/migration/migration-test.h   |  1 +
 tests/migration/ppc64/a-b-kernel.h | 42 +++
 tests/qtest/migration-test.c   | 37 +++--
 tests/migration/Makefile   |  2 +-
 tests/migration/ppc64/Makefile | 15 +++
 tests/migration/ppc64/a-b-kernel.S | 66 ++
 6 files changed, 131 insertions(+), 32 deletions(-)
 create mode 100644 tests/migration/ppc64/a-b-kernel.h
 create mode 100644 tests/migration/ppc64/Makefile
 create mode 100644 tests/migration/ppc64/a-b-kernel.S

diff --git a/tests/migration/migration-test.h b/tests/migration/migration-test.h
index 68512c0b1b..194df7df6f 100644
--- a/tests/migration/migration-test.h
+++ b/tests/migration/migration-test.h
@@ -22,6 +22,7 @@
 /* PPC */
 #define PPC_TEST_MEM_START (1 * 1024 * 1024)
 #define PPC_TEST_MEM_END   (100 * 1024 * 1024)
+#define PPC_H_PUT_TERM_CHAR 0x58
 
 /* ARM */
 #define ARM_TEST_MEM_START (0x4000 + 1 * 1024 * 1024)
diff --git a/tests/migration/ppc64/a-b-kernel.h 
b/tests/migration/ppc64/a-b-kernel.h
new file mode 100644
index 00..673317efdb
--- /dev/null
+++ b/tests/migration/ppc64/a-b-kernel.h
@@ -0,0 +1,42 @@
+/* This file is automatically generated from the assembly file in
+ * tests/migration/ppc64. 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 ppc64_kernel[] = {
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x7d, 0x20, 0x00, 0xa6, 0x39, 0x40, 0xff, 0xff,
+  0x79, 0x49, 0xf8, 0x0e, 0x7d, 0x20, 0x01, 0x64, 0x3e, 0x80, 0x00, 0x10,
+  0x62, 0x94, 0x00, 0x00, 0x3d, 0x20, 0x06, 0x40, 0x61, 0x29, 0x00, 0x00,
+  0x7e, 0xb4, 0x48, 0x50, 0x39, 0x40, 0x10, 0x00, 0x7e, 0xb5, 0x53, 0xd2,
+  0x38, 0x60, 0x00, 0x58, 0x38, 0x80, 0x00, 0x00, 0x38, 0xa0, 0x00, 0x01,
+  0x38, 0xc0, 0x00, 0x41, 0x78, 0xc6, 0xc1, 0xc6, 0x44, 0x00, 0x00, 0x22,
+  0x38, 0x60, 0x00, 0x00, 0x7e, 0x89, 0xa3, 0x78, 0x7e, 0xa9, 0x03, 0xa6,
+  0x98, 0x69, 0x00, 0x00, 0x39, 0x29, 0x10, 0x00, 0x42, 0x00, 0xff, 0xf8,
+  0x7e, 0x89, 0xa3, 0x78, 0x7e, 0xa9, 0x03, 0xa6, 0x88, 0x69, 0x00, 0x00,
+  0x38, 0x63, 0x00, 0x01, 0x98, 0x69, 0x00, 0x00, 0x39, 0x29, 0x10, 0x00,
+  0x42, 0x00, 0xff, 0xf0, 0x38, 0x60, 0x00, 0x58, 0x38, 0x80, 0x00, 0x00,
+  0x38, 0xa0, 0x00, 0x01, 0x38, 0xc0, 0x00, 0x42, 0x78, 0xc6, 0xc1, 0xc6,
+  0x44, 0x00, 0x00, 0x22, 0x4b, 0xff, 0xff, 0xcc
+};
+
diff --git a/tests/qtest/migration-test.c b/tests/qtest/migration-test.c
index 87fa733d60..45830eb213 100644
--- a/tests/qtest/migration-test.c
+++ b/tests/qtest/migration-test.c
@@ -128,6 +128,7 @@ static char *bootpath;
  */
 #include "tests/migration/i386/a-b-bootblock.h"
 #include "tests/migration/aarch64/a-b-kernel.h"
+#include "tests/migration/ppc64/a-b-kernel.h"
 #include "tests/migration/s390x/a-b-bios.h"
 
 static void bootfile_create(char *dir, bool suspend_me)
@@ -147,10 +148,8 @@ static void bootfile_create(char *dir, bool suspend_me)
 content = s390x_elf;
 len = sizeof(s390x_elf);
 } else if (strcmp(arch, "ppc64&q

[PATCH v2 5/6] tests/qtest/migration-test: Enable on ppc64 TCG

2024-05-27 Thread Nicholas Piggin
ppc64 with TCG seems to no longer be failing this test, perhaps since
commit 03bfc2188f061 ("physmem: Fix migration dirty bitmap coherency
with TCG memory access") which is not ppc specific but was seen to hit
ppc64 quite easily.

Let's enable it again.

The s390x problem has been identified so mention it while we are
adjusting the comment.

Reviewed-by: Thomas Huth 
Signed-off-by: Nicholas Piggin 
---
 tests/qtest/migration-test.c | 16 +++-
 1 file changed, 3 insertions(+), 13 deletions(-)

diff --git a/tests/qtest/migration-test.c b/tests/qtest/migration-test.c
index 7d64696f7a..87fa733d60 100644
--- a/tests/qtest/migration-test.c
+++ b/tests/qtest/migration-test.c
@@ -3463,19 +3463,9 @@ int main(int argc, char **argv)
 #endif
 
 /*
- * On ppc64, the test only works with kvm-hv, but not with kvm-pr and TCG
- * is touchy due to race conditions on dirty bits (especially on PPC for
- * some reason)
- */
-if (g_str_equal(arch, "ppc64") &&
-(!has_kvm || access("/sys/module/kvm_hv", F_OK))) {
-g_test_message("Skipping tests: kvm_hv not available");
-goto test_add_done;
-}
-
-/*
- * Similar to ppc64, s390x seems to be touchy with TCG, so disable it
- * there until the problems are resolved
+ * On s390x with TCG, migration is observed to hang due to the 'pending'
+ * state of the flic interrupt controller not being migrated or
+ * reconstructed post-migration. Disable it until the problem is resolved.
  */
 if (g_str_equal(arch, "s390x") && !has_kvm) {
 g_test_message("Skipping tests: s390x host with KVM is required");
-- 
2.43.0




[PATCH v2 4/6] tests/qtest/migration-test: Quieten ppc64 QEMU warnigns

2024-05-27 Thread Nicholas Piggin
Reviewed-by: Thomas Huth 
Signed-off-by: Nicholas Piggin 
---
 tests/qtest/migration-test.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/tests/qtest/migration-test.c b/tests/qtest/migration-test.c
index 8247ed98f2..7d64696f7a 100644
--- a/tests/qtest/migration-test.c
+++ b/tests/qtest/migration-test.c
@@ -21,6 +21,7 @@
 #include "chardev/char.h"
 #include "crypto/tlscredspsk.h"
 #include "qapi/qmp/qlist.h"
+#include "ppc-util.h"
 
 #include "migration-helpers.h"
 #include "tests/migration/migration-test.h"
@@ -750,7 +751,8 @@ static int test_migrate_start(QTestState **from, QTestState 
**to,
   "until'", end_address, start_address);
 machine_alias = "pseries";
 machine_opts = "vsmt=8";
-arch_opts = g_strdup("-nodefaults");
+arch_opts = g_strdup("-nodefaults "
+ "-machine " PSERIES_DEFAULT_CAPABILITIES);
 } else if (strcmp(arch, "aarch64") == 0) {
 memory_size = "150M";
 machine_alias = "virt";
-- 
2.43.0




[PATCH v2 3/6] tests/qtest: Move common define from libqos-spapr.h to new ppc-util.h

2024-05-27 Thread Nicholas Piggin
The spapr QEMU machine defaults is useful outside libqos, so create a
new header for ppc specific qtests and move it there.

Signed-off-by: Nicholas Piggin 
---
 tests/qtest/libqos/libqos-spapr.h |  7 ---
 tests/qtest/ppc-util.h| 19 +++
 tests/qtest/boot-serial-test.c|  2 +-
 tests/qtest/prom-env-test.c   |  2 +-
 tests/qtest/pxe-test.c|  2 +-
 5 files changed, 22 insertions(+), 10 deletions(-)
 create mode 100644 tests/qtest/ppc-util.h

diff --git a/tests/qtest/libqos/libqos-spapr.h 
b/tests/qtest/libqos/libqos-spapr.h
index e4483c14f8..a446276416 100644
--- a/tests/qtest/libqos/libqos-spapr.h
+++ b/tests/qtest/libqos/libqos-spapr.h
@@ -9,11 +9,4 @@ QOSState *qtest_spapr_boot(const char *cmdline_fmt, ...)
 G_GNUC_PRINTF(1, 2);
 void qtest_spapr_shutdown(QOSState *qs);
 
-/* List of capabilities needed to silence warnings with TCG */
-#define PSERIES_DEFAULT_CAPABILITIES \
-"cap-cfpc=broken,"   \
-"cap-sbbc=broken,"   \
-"cap-ibs=broken,"\
-"cap-ccf-assist=off,"
-
 #endif
diff --git a/tests/qtest/ppc-util.h b/tests/qtest/ppc-util.h
new file mode 100644
index 00..f68ee93520
--- /dev/null
+++ b/tests/qtest/ppc-util.h
@@ -0,0 +1,19 @@
+/*
+ * PowerPC misc useful things
+ *
+ * Copyright (c) 2024, IBM Corporation.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#ifndef PPC_UTIL_H
+#define PPC_UTIL_H
+
+/* List of capabilities needed to silence warnings with TCG */
+#define PSERIES_DEFAULT_CAPABILITIES \
+"cap-cfpc=broken,"   \
+"cap-sbbc=broken,"   \
+"cap-ibs=broken,"\
+"cap-ccf-assist=off,"
+
+#endif /* PPC_UTIL_H */
diff --git a/tests/qtest/boot-serial-test.c b/tests/qtest/boot-serial-test.c
index df389adeeb..3b92fa5d50 100644
--- a/tests/qtest/boot-serial-test.c
+++ b/tests/qtest/boot-serial-test.c
@@ -15,7 +15,7 @@
 
 #include "qemu/osdep.h"
 #include "libqtest.h"
-#include "libqos/libqos-spapr.h"
+#include "ppc-util.h"
 
 static const uint8_t bios_avr[] = {
 0x88, 0xe0, /* ldi r24, 0x08   */
diff --git a/tests/qtest/prom-env-test.c b/tests/qtest/prom-env-test.c
index 39ccb59797..14705105ad 100644
--- a/tests/qtest/prom-env-test.c
+++ b/tests/qtest/prom-env-test.c
@@ -21,7 +21,7 @@
 
 #include "qemu/osdep.h"
 #include "libqtest.h"
-#include "libqos/libqos-spapr.h"
+#include "ppc-util.h"
 
 #define MAGIC   0xcafec0de
 #define ADDRESS 0x4000
diff --git a/tests/qtest/pxe-test.c b/tests/qtest/pxe-test.c
index e4b48225a5..a3f900fbea 100644
--- a/tests/qtest/pxe-test.c
+++ b/tests/qtest/pxe-test.c
@@ -16,7 +16,7 @@
 #include 
 #include "libqtest.h"
 #include "boot-sector.h"
-#include "libqos/libqos-spapr.h"
+#include "ppc-util.h"
 
 #define NETNAME "net0"
 
-- 
2.43.0




[PATCH v2 1/6] tests/qtest/migration: Run test_mode_reboot outside gitlab CI

2024-05-27 Thread Nicholas Piggin
As Fabiano points out, this test isn't flaky it just can't run under
gitlab CI since runners have a very small shm size.

Suggested-by: Fabiano Rosas 
Signed-off-by: Nicholas Piggin 
---
 tests/qtest/migration-test.c | 18 +-
 1 file changed, 9 insertions(+), 9 deletions(-)

diff --git a/tests/qtest/migration-test.c b/tests/qtest/migration-test.c
index b7e3406471..04bf1c0092 100644
--- a/tests/qtest/migration-test.c
+++ b/tests/qtest/migration-test.c
@@ -706,6 +706,14 @@ static int test_migrate_start(QTestState **from, 
QTestState **to,
 g_test_skip("/dev/shm is not supported");
 return -1;
 }
+if (getenv("GITLAB_CI")) {
+/*
+ * Gitlab runners are limited to 64MB shm size. See:
+ * https://lore.kernel.org/all/87ttq5fvh7@suse.de/
+ */
+g_test_skip("/dev/shm is not supported in Gitlab CI environment");
+return -1;
+}
 }
 
 dst_state = (QTestMigrationState) { };
@@ -3506,15 +3514,7 @@ int main(int argc, char **argv)
test_precopy_file_offset);
 migration_test_add("/migration/precopy/file/offset/bad",
test_precopy_file_offset_bad);
-
-/*
- * Our CI system has problems with shared memory.
- * Don't run this test until we find a workaround.
- */
-if (getenv("QEMU_TEST_FLAKY_TESTS")) {
-migration_test_add("/migration/mode/reboot", test_mode_reboot);
-}
-
+migration_test_add("/migration/mode/reboot", test_mode_reboot);
 migration_test_add("/migration/precopy/file/mapped-ram",
test_precopy_file_mapped_ram);
 migration_test_add("/migration/precopy/file/mapped-ram/live",
-- 
2.43.0




[PATCH v2 2/6] tests/qtest/migration-test: Fix and enable test_ignore_shared

2024-05-27 Thread Nicholas Piggin
This test is already starting to bitrot, so first remove it from ifdef
and fix compile issues. ppc64 transfers about 2MB, so bump the size
threshold too.

It was said to be broken on aarch64 but it may have been the limited shm
size under gitlab CI. The test is now excluded from running on CI so it
shouldn't cause too much annoyance.

So let's try enable it.

Cc: Yury Kotov 
Cc: Dr. David Alan Gilbert 
Signed-off-by: Nicholas Piggin 
---
 tests/qtest/migration-test.c | 14 --
 1 file changed, 8 insertions(+), 6 deletions(-)

diff --git a/tests/qtest/migration-test.c b/tests/qtest/migration-test.c
index 04bf1c0092..8247ed98f2 100644
--- a/tests/qtest/migration-test.c
+++ b/tests/qtest/migration-test.c
@@ -1893,14 +1893,15 @@ static void 
test_precopy_unix_tls_x509_override_host(void)
 #endif /* CONFIG_TASN1 */
 #endif /* CONFIG_GNUTLS */
 
-#if 0
-/* Currently upset on aarch64 TCG */
 static void test_ignore_shared(void)
 {
 g_autofree char *uri = g_strdup_printf("unix:%s/migsocket", tmpfs);
 QTestState *from, *to;
+MigrateStart args = {
+.use_shmem = true,
+};
 
-if (test_migrate_start(, , uri, false, true, NULL, NULL)) {
+if (test_migrate_start(, , uri, )) {
 return;
 }
 
@@ -1925,11 +1926,11 @@ static void test_ignore_shared(void)
 wait_for_migration_complete(from);
 
 /* Check whether shared RAM has been really skipped */
-g_assert_cmpint(read_ram_property_int(from, "transferred"), <, 1024 * 
1024);
+g_assert_cmpint(read_ram_property_int(from, "transferred"), <,
+   4 * 1024 * 1024);
 
 test_migrate_end(from, to, true);
 }
-#endif
 
 static void *
 test_migrate_xbzrle_start(QTestState *from,
@@ -3580,7 +3581,8 @@ int main(int argc, char **argv)
 #endif /* CONFIG_TASN1 */
 #endif /* CONFIG_GNUTLS */
 
-/* migration_test_add("/migration/ignore_shared", test_ignore_shared); */
+migration_test_add("/migration/ignore_shared", test_ignore_shared);
+
 #ifndef _WIN32
 migration_test_add("/migration/precopy/fd/tcp",
test_migrate_precopy_fd_socket);
-- 
2.43.0




[PATCH v2 0/6] tests/qtest/migration-test: Improve and enable on ppc64

2024-05-27 Thread Nicholas Piggin
Since v1:
- Added "TCG" in subject since it is enabling for TCG
- Enable test_mode_reboot with checking GITLAB_CI env that Fabiano
  suggested.
- Move test_ignore_shared patch out of the s390 fix series to here
  and use GITLAB_CI for it too.
- Move ppc64 pseries machine options out of libqos-spapr.h to a
  new general qtest ppc header.
- Adjust remaining s390x comment to explain the problem.

Thanks,
Nick

Nicholas Piggin (6):
  tests/qtest/migration: Run test_mode_reboot outside gitlab CI
  tests/qtest/migration-test: Fix and enable test_ignore_shared
  tests/qtest: Move common define from libqos-spapr.h to new ppc-util.h
  tests/qtest/migration-test: Quieten ppc64 QEMU warnigns
  tests/qtest/migration-test: Enable on ppc64 TCG
  tests/qtest/migration-test: Use custom asm bios for ppc64

 tests/migration/migration-test.h   |  1 +
 tests/migration/ppc64/a-b-kernel.h | 42 +++
 tests/qtest/libqos/libqos-spapr.h  |  7 ---
 tests/qtest/ppc-util.h | 19 +++
 tests/qtest/boot-serial-test.c |  2 +-
 tests/qtest/migration-test.c   | 85 ++
 tests/qtest/prom-env-test.c|  2 +-
 tests/qtest/pxe-test.c |  2 +-
 tests/migration/Makefile   |  2 +-
 tests/migration/ppc64/Makefile | 15 ++
 tests/migration/ppc64/a-b-kernel.S | 66 +++
 11 files changed, 174 insertions(+), 69 deletions(-)
 create mode 100644 tests/migration/ppc64/a-b-kernel.h
 create mode 100644 tests/qtest/ppc-util.h
 create mode 100644 tests/migration/ppc64/Makefile
 create mode 100644 tests/migration/ppc64/a-b-kernel.S

-- 
2.43.0




Re: [PATCH 2/3] tests/qtest/migration-test: Enable on ppc64

2024-05-27 Thread Nicholas Piggin
On Mon May 27, 2024 at 5:35 PM AEST, Thomas Huth wrote:
> On 25/05/2024 05.13, Nicholas Piggin wrote:
> > ppc64 with TCG seems to no longer be failing this test. Let's try to
> > enable it. s390x is still hanging about 1 in 10 runs.
> > 
> > Signed-off-by: Nicholas Piggin 
> > ---
> >   tests/qtest/migration-test.c | 16 +++-
> >   1 file changed, 3 insertions(+), 13 deletions(-)
> > 
> > diff --git a/tests/qtest/migration-test.c b/tests/qtest/migration-test.c
> > index c13535c37d..b8617cc843 100644
> > --- a/tests/qtest/migration-test.c
> > +++ b/tests/qtest/migration-test.c
> > @@ -3454,19 +3454,9 @@ int main(int argc, char **argv)
> >   #endif
> >   
> >   /*
> > - * On ppc64, the test only works with kvm-hv, but not with kvm-pr and 
> > TCG
> > - * is touchy due to race conditions on dirty bits (especially on PPC 
> > for
> > - * some reason)
> > - */
> > -if (g_str_equal(arch, "ppc64") &&
> > -(!has_kvm || access("/sys/module/kvm_hv", F_OK))) {
> > -g_test_message("Skipping tests: kvm_hv not available");
> > -goto test_add_done;
> > -}
> > -
> > -/*
> > - * Similar to ppc64, s390x seems to be touchy with TCG, so disable it
> > - * there until the problems are resolved
> > + * On s390x, the test seems to be touchy with TCG, perhaps due to race
> > + * conditions on dirty bits, so disable it there until the problems are
> > + * resolved.
> >*/
> >   if (g_str_equal(arch, "s390x") && !has_kvm) {
> >   g_test_message("Skipping tests: s390x host with KVM is required");
>
> Since you've identified the problem on s390x, you could maybe adjust the 
> comment in case you respin ... OTOH, it will get removed anyway once we 
> merge the s390x fix, so no need to respin just because of this.
>
> Reviewed-by: Thomas Huth 

Thanks. I will respin to at least fix the subjet "Enable on ppc64 TCG"
so I can do the other minor things too.

Thanks,
Nick



Re: [PATCH 1/3] tests/qtest/migration-test: Quieten ppc64 QEMU warnigns

2024-05-27 Thread Nicholas Piggin
On Mon May 27, 2024 at 5:32 PM AEST, Thomas Huth wrote:
> On 25/05/2024 05.13, Nicholas Piggin wrote:
> > Signed-off-by: Nicholas Piggin 
> > ---
> >   tests/qtest/migration-test.c | 4 +++-
> >   1 file changed, 3 insertions(+), 1 deletion(-)
> > 
> > diff --git a/tests/qtest/migration-test.c b/tests/qtest/migration-test.c
> > index b7e3406471..c13535c37d 100644
> > --- a/tests/qtest/migration-test.c
> > +++ b/tests/qtest/migration-test.c
> > @@ -21,6 +21,7 @@
> >   #include "chardev/char.h"
> >   #include "crypto/tlscredspsk.h"
> >   #include "qapi/qmp/qlist.h"
> > +#include "libqos/libqos-spapr.h"
>
> It's a little bit unfortunate to include a libqos header in a non-qos test 
> ... so in case you respin, maybe add a comment at the end of the line like:
>
>/* just for PSERIES_DEFAULT_CAPABILITIES */
>
> ?

Same as other uses of it by the looks. Could just put it in a new
header in tests/qtest/ppc-util.h or something?

Thanks,
Nick

>
> >   #include "migration-helpers.h"
> >   #include "tests/migration/migration-test.h"
> > @@ -742,7 +743,8 @@ static int test_migrate_start(QTestState **from, 
> > QTestState **to,
> > "until'", end_address, 
> > start_address);
> >   machine_alias = "pseries";
> >   machine_opts = "vsmt=8";
> > -arch_opts = g_strdup("-nodefaults");
> > +arch_opts = g_strdup_printf("-nodefaults "
> > +"-machine " PSERIES_DEFAULT_CAPABILITIES);
> >   } else if (strcmp(arch, "aarch64") == 0) {
> >   memory_size = "150M";
> >   machine_alias = "virt";
>
>   Reviewed-by: Thomas Huth 




Re: [RFC PATCH 00/10] ppc/pnv: Better big-core model, lpar-per-core, PC unit

2024-05-27 Thread Nicholas Piggin
On Mon May 27, 2024 at 4:25 PM AEST, Cédric Le Goater wrote:
> On 5/26/24 14:26, Nicholas Piggin wrote:
> > Primary motivation for this series is to improve big-core support.
> > Other things like SPR indirect, timebase state, PC xscom, are required
> > for minimal big core support.
> > 
> > I'm still not 100% happy with the big-core topology model after this.
> > Maybe one day we add pnv big core and pnv small core structures. But
>
> I haven't look at the proposal yet, but indeed, we could introduce
> a new TYPE_PNV_CORE type for big cores only.

Yeah. It's still tricky because big-core structure contains the CPUs
if you are running in small core mode. So it would really have to be
a PnvCPUCore and PnvPervasiveCore or something, where the former is
either SMT4 and 1:1 with the latter or SMT8 and 1:2 depending on mode.

And some of the "CPU" type operations in big core mode still need to
operate on the small core.

For now, the accessors and helpers seem to be not too bad.

> > nothing is completely clean because big core mode still has certain
> > small core restrictions. I think for now we take a bit of mostly
> > abstracted ugliness in TCG code for the benefit of not spreading
> > hacks through pervasive (xscom) core addressing.
> > 
> > After this series, power9 and power10 get through skiboot/Linux boot
> s
>
> Have you tried SMT8 on powernv8 ? I remember seeing a hang if I am correct.
> I don't think POWER8 deserves much attention anymore, we could deprecate
> POWER8E and POWER8NVL. However, we should at least report an error if we
> know a setup is broken.

Yeah it does have some problem. Maybe should just disable SMT unless
someone finds time to work it out.

Thanks,
Nick



Re: [RFC PATCH 1/3] hw/intc/s390_flic: Migrate pending state

2024-05-27 Thread Nicholas Piggin
On Mon May 27, 2024 at 3:51 PM AEST, Thomas Huth wrote:
> On 26/05/2024 22.33, David Hildenbrand wrote:
> > Am 26.05.24 um 21:44 schrieb Richard Henderson:
> >> On 5/26/24 08:53, David Hildenbrand wrote:
> >>> Am 25.05.24 um 15:12 schrieb Nicholas Piggin:
> >>>> The flic pending state is not migrated, so if the machine is migrated
> >>>> while an interrupt is pending, it can be lost. This shows up in
> >>>> qtest migration test, an extint is pending (due to console writes?)
> >>>> and the CPU waits via s390_cpu_set_psw and expects the interrupt to
> >>>> wake it. However when the flic pending state is lost, s390_cpu_has_int
> >>>> returns false, so s390_cpu_exec_interrupt falls through to halting
> >>>> again.
> >>>>
> >>>> Fix this by migrating pending. This prevents the qtest from hanging.
> >>>> Does service_param need to be migrated? Or the IO lists?
> >>>>
> >>>> Signed-off-by: Nicholas Piggin 
> >>>> ---
> >>>>   hw/intc/s390_flic.c | 1 +
> >>>>   1 file changed, 1 insertion(+)
> >>>>
> >>>> diff --git a/hw/intc/s390_flic.c b/hw/intc/s390_flic.c
> >>>> index 6771645699..b70cf2295a 100644
> >>>> --- a/hw/intc/s390_flic.c
> >>>> +++ b/hw/intc/s390_flic.c
> >>>> @@ -369,6 +369,7 @@ static const VMStateDescription 
> >>>> qemu_s390_flic_vmstate = {
> >>>>   .fields = (const VMStateField[]) {
> >>>>   VMSTATE_UINT8(simm, QEMUS390FLICState),
> >>>>   VMSTATE_UINT8(nimm, QEMUS390FLICState),
> >>>> +    VMSTATE_UINT32(pending, QEMUS390FLICState),
> >>>>   VMSTATE_END_OF_LIST()
> >>>>   }
> >>>>   };
> >>>
> >>> Likely you have to handle this using QEMU compat machines.
> >>
> >> Well, since existing migration is broken, I don't think you have to 
> >> preserve 
> > 
> > Migration is broken only in some case "while an interrupt is pending, it 
> > can 
> > be lost".
> > 
> >> compatibility.  But you do have to bump the version number.
> > 
> > Looking at it, this is TCG only, so likely we don't care that much about 
> > migration compatibility. But I have no idea what level of compatibility we 
> > want to support there.
>
> Yes, this seems to only affect the TCG-only flic device, where migration has 
> never been working very reliably. So I think we don't really need the whole 
> compat-machine dance here. But I think we should at least bump the 
> version_id to 2 now and then use
>
> VMSTATE_UINT32_V(pending, QEMUS390FLICState, 2);
>
> for the new field. That way we would at least support forward migrations 
> without too much hassle.

Well if you could rebuild this state by checking sources or something
it might be possible to avoid. Or if you could always mark pending and
software can tolerate superflous. But that also seems like a lot of
headache for something that was always flaky.

Thanks,
Nick



Re: [RFC PATCH 2/3] tests/qtest/migration-test: enable on s390x

2024-05-27 Thread Nicholas Piggin
On Mon May 27, 2024 at 3:46 PM AEST, Prasad Pandit wrote:
> Hi,
>
> On Sat, 25 May 2024 at 18:44, Nicholas Piggin  wrote:
> > s390x is more stable now. Enable it.
> >
> > Signed-off-by: Nicholas Piggin 
> > ---
> >  tests/qtest/migration-test.c | 12 
> >  1 file changed, 12 deletions(-)
> >
> > diff --git a/tests/qtest/migration-test.c b/tests/qtest/migration-test.c
> > index 94d5057857..7987faaded 100644
> > --- a/tests/qtest/migration-test.c
> > +++ b/tests/qtest/migration-test.c
> > @@ -3428,16 +3428,6 @@ int main(int argc, char **argv)
> >  migration_test_add("/migration/analyze-script", test_analyze_script);
> >  #endif
> >
> > -/*
> > - * On s390x, the test seems to be touchy with TCG, perhaps due to race
> > - * conditions on dirty bits, so disable it there until the problems are
> > - * resolved.
> > - */
>
> -> https://lists.nongnu.org/archive/html/qemu-devel/2024-05/msg04774.html
>
> * Above patch (not reviewed yet) adds comment about sporadic problems
> on s390x, and this patch says s390x is stable now? It'll help to
> mention in the commit log - what changed to make it stable in 1 day.

Patch 1 of this series.

> * IIUC, this and the ppc64 patch above enable 'migration-test' for
> s390x and ppc64 platforms, when KVM is not available for them? ie.
> When running s390x & ppc64 migration-tests with TCG on non s390x or
> non-ppc64 machines, right? Maybe the commit message could say
> something to the effect of - enable s390x and ppc64 'migration-test'
> to run with TCG across platforms where KVM for s390x  OR  KVM for
> ppc64 is not available.

Yes they should be called "enable for TCG" indeed.

> > -if (g_str_equal(arch, "s390x") && !has_kvm) {
> > -g_test_message("Skipping tests: s390x host with KVM is required");
> > -goto test_add_done;
> > -}
> > -
> >  if (is_x86) {
> >  migration_test_add("/migration/precopy/unix/suspend/live",
> > test_precopy_unix_suspend_live);
> > @@ -3619,8 +3609,6 @@ int main(int argc, char **argv)
> > test_vcpu_dirty_limit);
> >  }
> >
> > -test_add_done:
> > -
> >  ret = g_test_run();
> >
> >  g_assert_cmpint(ret, ==, 0);
> > --
>
> * Otherwise, the change looks okay to enable 'migration-test' for
> s390x with TCG IIUC.

Thanks,
Nick



[RFC PATCH 09/10] ppc/pnv: Implement POWER10 PC xscom registers for direct controls

2024-05-26 Thread Nicholas Piggin
The PC unit in the processor core contains xscom registers that provide
low level status and control of the CPU.

This implements "direct controls" sufficient for OPAL (skiboot) firmware
use, which is to stop threads and send them non-maskable IPIs in the
form of SRESET interrupts.

POWER10 is sufficiently different (particularly QME and special wakeup)
from POWER9 that it is not trivial to implement by reusing the code.

Signed-off-by: Nicholas Piggin 
---
 include/hw/core/cpu.h |  8 
 include/hw/ppc/pnv.h  |  2 +
 include/hw/ppc/pnv_core.h |  3 ++
 hw/ppc/pnv.c  |  7 +++-
 hw/ppc/pnv_core.c | 88 ---
 system/cpus.c | 10 +
 6 files changed, 112 insertions(+), 6 deletions(-)

diff --git a/include/hw/core/cpu.h b/include/hw/core/cpu.h
index bb398e8237..52a8fc65cb 100644
--- a/include/hw/core/cpu.h
+++ b/include/hw/core/cpu.h
@@ -974,6 +974,14 @@ void cpu_reset_interrupt(CPUState *cpu, int mask);
  */
 void cpu_exit(CPUState *cpu);
 
+/**
+ * cpu_pause:
+ * @cpu: The CPU to pause.
+ *
+ * Resumes CPU, i.e. puts CPU into stopped state.
+ */
+void cpu_pause(CPUState *cpu);
+
 /**
  * cpu_resume:
  * @cpu: The CPU to resume.
diff --git a/include/hw/ppc/pnv.h b/include/hw/ppc/pnv.h
index 93ecb062b4..bec603f1a8 100644
--- a/include/hw/ppc/pnv.h
+++ b/include/hw/ppc/pnv.h
@@ -111,6 +111,8 @@ PnvChip *pnv_chip_add_phb(PnvChip *chip, PnvPHB *phb);
 #define PNV_FDT_ADDR  0x0100
 #define PNV_TIMEBASE_FREQ 51200ULL
 
+void pnv_cpu_do_nmi(CPUState *cs);
+
 /*
  * BMC helpers
  */
diff --git a/include/hw/ppc/pnv_core.h b/include/hw/ppc/pnv_core.h
index 39f8f33e6c..9599da15ea 100644
--- a/include/hw/ppc/pnv_core.h
+++ b/include/hw/ppc/pnv_core.h
@@ -109,6 +109,9 @@ OBJECT_DECLARE_TYPE(PnvQuad, PnvQuadClass, PNV_QUAD)
 struct PnvQuad {
 DeviceState parent_obj;
 
+bool special_wakeup_done;
+bool special_wakeup[4];
+
 uint32_t quad_id;
 MemoryRegion xscom_regs;
 MemoryRegion xscom_qme_regs;
diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c
index 5364c55bbb..765142965f 100644
--- a/hw/ppc/pnv.c
+++ b/hw/ppc/pnv.c
@@ -2700,12 +2700,17 @@ static void pnv_cpu_do_nmi_on_cpu(CPUState *cs, 
run_on_cpu_data arg)
 }
 }
 
+void pnv_cpu_do_nmi(CPUState *cs)
+{
+async_run_on_cpu(cs, pnv_cpu_do_nmi_on_cpu, RUN_ON_CPU_NULL);
+}
+
 static void pnv_nmi(NMIState *n, int cpu_index, Error **errp)
 {
 CPUState *cs;
 
 CPU_FOREACH(cs) {
-async_run_on_cpu(cs, pnv_cpu_do_nmi_on_cpu, RUN_ON_CPU_NULL);
+pnv_cpu_do_nmi(cs);
 }
 }
 
diff --git a/hw/ppc/pnv_core.c b/hw/ppc/pnv_core.c
index 10417d92ae..835c35d90b 100644
--- a/hw/ppc/pnv_core.c
+++ b/hw/ppc/pnv_core.c
@@ -184,16 +184,40 @@ static const MemoryRegionOps pnv_core_power9_xscom_ops = {
  */
 
 #define PNV10_XSCOM_EC_CORE_THREAD_STATE0x412
+#define PNV10_XSCOM_EC_CORE_THREAD_INFO 0x413
+#define PNV10_XSCOM_EC_CORE_DIRECT_CONTROLS 0x449
+#define PNV10_XSCOM_EC_CORE_RAS_STATUS  0x454
 
 static uint64_t pnv_core_power10_xscom_read(void *opaque, hwaddr addr,
unsigned int width)
 {
+PnvCore *pc = PNV_CORE(opaque);
+int nr_threads = CPU_CORE(pc)->nr_threads;
+int i;
 uint32_t offset = addr >> 3;
 uint64_t val = 0;
 
 switch (offset) {
 case PNV10_XSCOM_EC_CORE_THREAD_STATE:
-val = 0;
+for (i = 0; i < nr_threads; i++) {
+PowerPCCPU *cpu = pc->threads[i];
+CPUState *cs = CPU(cpu);
+
+if (cs->halted) {
+val |= PPC_BIT(56 + i);
+}
+}
+break;
+case PNV10_XSCOM_EC_CORE_THREAD_INFO:
+break;
+case PNV10_XSCOM_EC_CORE_RAS_STATUS:
+for (i = 0; i < nr_threads; i++) {
+PowerPCCPU *cpu = pc->threads[i];
+CPUState *cs = CPU(cpu);
+if (cs->stopped) {
+val |= PPC_BIT(0 + 8*i) | PPC_BIT(1 + 8*i);
+}
+}
 break;
 default:
 qemu_log_mask(LOG_UNIMP, "%s: unimp read 0x%08x\n", __func__,
@@ -206,9 +230,45 @@ static uint64_t pnv_core_power10_xscom_read(void *opaque, 
hwaddr addr,
 static void pnv_core_power10_xscom_write(void *opaque, hwaddr addr,
  uint64_t val, unsigned int width)
 {
+PnvCore *pc = PNV_CORE(opaque);
+int nr_threads = CPU_CORE(pc)->nr_threads;
+int i;
 uint32_t offset = addr >> 3;
 
 switch (offset) {
+case PNV10_XSCOM_EC_CORE_DIRECT_CONTROLS:
+for (i = 0; i < nr_threads; i++) {
+PowerPCCPU *cpu = pc->threads[i];
+CPUState *cs = CPU(cpu);
+
+if (val & PPC_BIT(7 + 8*i)) { /* stop */
+val &= ~PPC_BIT(7 + 8*i);
+cpu_pause(cs);
+}
+if (val & PPC_BIT(6 + 8*i)) { /* start */
+val &= ~PPC_BIT(6 + 8*i);
+   

[RFC PATCH 00/10] ppc/pnv: Better big-core model, lpar-per-core, PC unit

2024-05-26 Thread Nicholas Piggin
Primary motivation for this series is to improve big-core support.
Other things like SPR indirect, timebase state, PC xscom, are required
for minimal big core support.

I'm still not 100% happy with the big-core topology model after this.
Maybe one day we add pnv big core and pnv small core structures. But
nothing is completely clean because big core mode still has certain
small core restrictions. I think for now we take a bit of mostly
abstracted ugliness in TCG code for the benefit of not spreading
hacks through pervasive (xscom) core addressing.

After this series, power9 and power10 get through skiboot/Linux boot
in SMT8 big-core mode. Not all big core registers are modeled
exactly (some are not shared between small core halves), but that
mostly doesn't matter for OPAL and it can be improved later.

Thanks,
Nick

Nicholas Piggin (10):
  ppc/pnv: Add pointer from PnvCPUState to PnvCore
  ppc/pnv: Move timebase state into PnvCore
  target/ppc: Improve SPR indirect registers
  ppc/pnv: specialise init for powernv8/9/10 machines
  ppc/pnv: Extend chip_pir class method to TIR as well
  ppc: Add a core_index to CPUPPCState for SMT vCPUs
  target/ppc: Add helpers to check for SMT sibling threads
  ppc/pnv: Invert the design for big-core machine modelling
  ppc/pnv: Implement POWER10 PC xscom registers for direct controls
  ppc/pnv: Add an LPAR per core machine option

 include/hw/core/cpu.h|   8 +
 include/hw/ppc/pnv.h |   6 +
 include/hw/ppc/pnv_chip.h|   3 +-
 include/hw/ppc/pnv_core.h|  31 
 target/ppc/cpu.h |  37 ++---
 hw/ppc/pnv.c | 297 ---
 hw/ppc/pnv_chiptod.c |   6 +-
 hw/ppc/pnv_core.c| 129 +--
 hw/ppc/spapr_cpu_core.c  |   7 +
 system/cpus.c|  10 ++
 target/ppc/cpu_init.c|  26 +--
 target/ppc/excp_helper.c |  16 +-
 target/ppc/misc_helper.c |  98 ++--
 target/ppc/timebase_helper.c |  82 +-
 14 files changed, 548 insertions(+), 208 deletions(-)

-- 
2.43.0




[RFC PATCH 05/10] ppc/pnv: Extend chip_pir class method to TIR as well

2024-05-26 Thread Nicholas Piggin
The chip_pir chip class method allows the platform to set the PIR
processor identification register. Extend this to a more general
ID function which also allows the TIR to be set. This is in
preparation for "big core", which is a more complicated topology
of cores and threads.

Signed-off-by: Nicholas Piggin 
---
 include/hw/ppc/pnv_chip.h |  3 +-
 hw/ppc/pnv.c  | 61 ---
 hw/ppc/pnv_core.c | 10 ---
 3 files changed, 45 insertions(+), 29 deletions(-)

diff --git a/include/hw/ppc/pnv_chip.h b/include/hw/ppc/pnv_chip.h
index 8589f3291e..679723926a 100644
--- a/include/hw/ppc/pnv_chip.h
+++ b/include/hw/ppc/pnv_chip.h
@@ -147,7 +147,8 @@ struct PnvChipClass {
 
 DeviceRealize parent_realize;
 
-uint32_t (*chip_pir)(PnvChip *chip, uint32_t core_id, uint32_t thread_id);
+void (*processor_id)(PnvChip *chip, uint32_t core_id, uint32_t thread_id,
+ uint32_t *pir, uint32_t *tir);
 void (*intc_create)(PnvChip *chip, PowerPCCPU *cpu, Error **errp);
 void (*intc_reset)(PnvChip *chip, PowerPCCPU *cpu);
 void (*intc_destroy)(PnvChip *chip, PowerPCCPU *cpu);
diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c
index a706de2e36..7d062ec16c 100644
--- a/hw/ppc/pnv.c
+++ b/hw/ppc/pnv.c
@@ -144,7 +144,7 @@ static int pnv_dt_core(PnvChip *chip, PnvCore *pc, void 
*fdt)
 PnvChipClass *pnv_cc = PNV_CHIP_GET_CLASS(chip);
 g_autofree uint32_t *servers_prop = g_new(uint32_t, smt_threads);
 int i;
-uint32_t pir;
+uint32_t pir, tir;
 uint32_t segs[] = {cpu_to_be32(28), cpu_to_be32(40),
0x, 0x};
 uint32_t tbfreq = PNV_TIMEBASE_FREQ;
@@ -155,7 +155,7 @@ static int pnv_dt_core(PnvChip *chip, PnvCore *pc, void 
*fdt)
 char *nodename;
 int cpus_offset = get_cpus_node(fdt);
 
-pir = pnv_cc->chip_pir(chip, pc->hwid, 0);
+pnv_cc->processor_id(chip, pc->hwid, 0, , );
 
 nodename = g_strdup_printf("%s@%x", dc->fw_name, pir);
 offset = fdt_add_subnode(fdt, cpus_offset, nodename);
@@ -237,7 +237,8 @@ static int pnv_dt_core(PnvChip *chip, PnvCore *pc, void 
*fdt)
 
 /* Build interrupt servers properties */
 for (i = 0; i < smt_threads; i++) {
-servers_prop[i] = cpu_to_be32(pnv_cc->chip_pir(chip, pc->hwid, i));
+pnv_cc->processor_id(chip, pc->hwid, i, , );
+servers_prop[i] = cpu_to_be32(pir);
 }
 _FDT((fdt_setprop(fdt, offset, "ibm,ppc-interrupt-server#s",
servers_prop, sizeof(*servers_prop) * smt_threads)));
@@ -249,14 +250,17 @@ static void pnv_dt_icp(PnvChip *chip, void *fdt, uint32_t 
hwid,
uint32_t nr_threads)
 {
 PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip);
-uint32_t pir = pcc->chip_pir(chip, hwid, 0);
-uint64_t addr = PNV_ICP_BASE(chip) | (pir << 12);
+uint32_t pir, tir;
+uint64_t addr;
 char *name;
 const char compat[] = "IBM,power8-icp\0IBM,ppc-xicp";
 uint32_t irange[2], i, rsize;
 uint64_t *reg;
 int offset;
 
+pcc->processor_id(chip, hwid, 0, , );
+addr = PNV_ICP_BASE(chip) | (pir << 12);
+
 irange[0] = cpu_to_be32(pir);
 irange[1] = cpu_to_be32(nr_threads);
 
@@ -1104,10 +1108,12 @@ static void pnv_power10_init(MachineState *machine)
  *   25:28  Core number
  *   29:31  Thread ID
  */
-static uint32_t pnv_chip_pir_p8(PnvChip *chip, uint32_t core_id,
-uint32_t thread_id)
+static void pnv_processor_id_p8(PnvChip *chip,
+uint32_t core_id, uint32_t thread_id,
+uint32_t *pir, uint32_t *tir)
 {
-return (chip->chip_id << 7) | (core_id << 3) | thread_id;
+*pir = (chip->chip_id << 7) | (core_id << 3) | thread_id;
+*tir = thread_id;
 }
 
 static void pnv_chip_power8_intc_create(PnvChip *chip, PowerPCCPU *cpu,
@@ -1159,15 +1165,17 @@ static void pnv_chip_power8_intc_print_info(PnvChip 
*chip, PowerPCCPU *cpu,
  *
  * We only care about the lower bits. uint32_t is fine for the moment.
  */
-static uint32_t pnv_chip_pir_p9(PnvChip *chip, uint32_t core_id,
-uint32_t thread_id)
+static void pnv_processor_id_p9(PnvChip *chip,
+uint32_t core_id, uint32_t thread_id,
+uint32_t *pir, uint32_t *tir)
 {
 if (chip->nr_threads == 8) {
-return (chip->chip_id << 8) | ((thread_id & 1) << 2) | (core_id << 3) |
+*pir = (chip->chip_id << 8) | ((thread_id & 1) << 2) | (core_id << 3) |
(thread_id >> 1);
 } else {
-return (chip->chip_id << 8) | (core_id << 2) | thread_id;
+*pir = (chip->chip_id << 8) | (core_id << 2) | thread_id;
 }
+*tir = thread_id;
 }
 
 /*
@@ -1181,15

[RFC PATCH 06/10] ppc: Add a core_index to CPUPPCState for SMT vCPUs

2024-05-26 Thread Nicholas Piggin
The way SMT thread siblings are matched is clunky, using hard-coded
logic that checks the PIR SPR.

Change that to use a new core_index variable in the CPUPPCState,
where all siblings have the same core_index. CPU realize routines have
flexibility in setting core/sibling topology.

Signed-off-by: Nicholas Piggin 
---
 target/ppc/cpu.h| 5 -
 hw/ppc/pnv_core.c   | 2 ++
 hw/ppc/spapr_cpu_core.c | 3 +++
 3 files changed, 9 insertions(+), 1 deletion(-)

diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h
index dac13d4dac..9a89083932 100644
--- a/target/ppc/cpu.h
+++ b/target/ppc/cpu.h
@@ -1247,6 +1247,9 @@ struct CPUArchState {
 /* when a memory exception occurs, the access type is stored here */
 int access_type;
 
+/* For SMT processors */
+int core_index;
+
 #if !defined(CONFIG_USER_ONLY)
 /* MMU context, only relevant for full system emulation */
 #if defined(TARGET_PPC64)
@@ -1404,7 +1407,7 @@ struct CPUArchState {
 };
 
 #define _CORE_ID(cs)\
-(POWERPC_CPU(cs)->env.spr_cb[SPR_PIR].default_value & ~(cs->nr_threads - 
1))
+(POWERPC_CPU(cs)->env.core_index)
 
 #define THREAD_SIBLING_FOREACH(cs, cs_sibling)  \
 CPU_FOREACH(cs_sibling) \
diff --git a/hw/ppc/pnv_core.c b/hw/ppc/pnv_core.c
index 9b5edd9e48..0f61aabb77 100644
--- a/hw/ppc/pnv_core.c
+++ b/hw/ppc/pnv_core.c
@@ -252,6 +252,8 @@ static void pnv_core_cpu_realize(PnvCore *pc, PowerPCCPU 
*cpu, Error **errp,
 pir_spr->default_value = pir;
 tir_spr->default_value = tir;
 
+env->core_index = core_hwid;
+
 /* Set time-base frequency to 512 MHz */
 cpu_ppc_tb_init(env, PNV_TIMEBASE_FREQ);
 }
diff --git a/hw/ppc/spapr_cpu_core.c b/hw/ppc/spapr_cpu_core.c
index e7c9edd033..059d372c8a 100644
--- a/hw/ppc/spapr_cpu_core.c
+++ b/hw/ppc/spapr_cpu_core.c
@@ -300,16 +300,19 @@ static PowerPCCPU *spapr_create_vcpu(SpaprCpuCore *sc, 
int i, Error **errp)
 g_autofree char *id = NULL;
 CPUState *cs;
 PowerPCCPU *cpu;
+CPUPPCState *env;
 
 obj = object_new(scc->cpu_type);
 
 cs = CPU(obj);
 cpu = POWERPC_CPU(obj);
+env = >env;
 /*
  * All CPUs start halted. CPU0 is unhalted from the machine level reset 
code
  * and the rest are explicitly started up by the guest using an RTAS call.
  */
 qdev_prop_set_bit(DEVICE(obj), "start-powered-off", true);
+env->core_index = cc->core_id;
 cs->cpu_index = cc->core_id + i;
 if (!spapr_set_vcpu_id(cpu, cs->cpu_index, errp)) {
 return NULL;
-- 
2.43.0




[RFC PATCH 01/10] ppc/pnv: Add pointer from PnvCPUState to PnvCore

2024-05-26 Thread Nicholas Piggin
This helps move core state from CPU to core structures.

Signed-off-by: Nicholas Piggin 
---
 include/hw/ppc/pnv_core.h | 1 +
 hw/ppc/pnv_core.c | 3 +++
 2 files changed, 4 insertions(+)

diff --git a/include/hw/ppc/pnv_core.h b/include/hw/ppc/pnv_core.h
index c6d62fd145..30c1e5b1a3 100644
--- a/include/hw/ppc/pnv_core.h
+++ b/include/hw/ppc/pnv_core.h
@@ -54,6 +54,7 @@ struct PnvCoreClass {
 #define PNV_CORE_TYPE_NAME(cpu_model) cpu_model PNV_CORE_TYPE_SUFFIX
 
 typedef struct PnvCPUState {
+PnvCore *core;
 Object *intc;
 } PnvCPUState;
 
diff --git a/hw/ppc/pnv_core.c b/hw/ppc/pnv_core.c
index f40ab721d6..7b0ea7812b 100644
--- a/hw/ppc/pnv_core.c
+++ b/hw/ppc/pnv_core.c
@@ -225,6 +225,7 @@ static const MemoryRegionOps pnv_core_power10_xscom_ops = {
 static void pnv_core_cpu_realize(PnvCore *pc, PowerPCCPU *cpu, Error **errp,
  int thread_index)
 {
+PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
 CPUPPCState *env = >env;
 int core_hwid;
 ppc_spr_t *pir = >spr_cb[SPR_PIR];
@@ -232,6 +233,8 @@ static void pnv_core_cpu_realize(PnvCore *pc, PowerPCCPU 
*cpu, Error **errp,
 Error *local_err = NULL;
 PnvChipClass *pcc = PNV_CHIP_GET_CLASS(pc->chip);
 
+pnv_cpu->core = pc;
+
 if (!qdev_realize(DEVICE(cpu), NULL, errp)) {
 return;
 }
-- 
2.43.0




[RFC PATCH 04/10] ppc/pnv: specialise init for powernv8/9/10 machines

2024-05-26 Thread Nicholas Piggin
This will allow different settings and checks for different
machine types with later changes.

Signed-off-by: Nicholas Piggin 
---
 hw/ppc/pnv.c | 35 ++-
 1 file changed, 30 insertions(+), 5 deletions(-)

diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c
index 6e3a5ccdec..a706de2e36 100644
--- a/hw/ppc/pnv.c
+++ b/hw/ppc/pnv.c
@@ -976,11 +976,6 @@ static void pnv_init(MachineState *machine)
 pnv->num_chips =
 machine->smp.max_cpus / (machine->smp.cores * machine->smp.threads);
 
-if (machine->smp.threads > 8) {
-error_report("Cannot support more than 8 threads/core "
- "on a powernv machine");
-exit(1);
-}
 if (!is_power_of_2(machine->smp.threads)) {
 error_report("Cannot support %d threads/core on a powernv"
  "machine because it must be a power of 2",
@@ -1076,6 +1071,33 @@ static void pnv_init(MachineState *machine)
 }
 }
 
+static void pnv_power8_init(MachineState *machine)
+{
+if (machine->smp.threads > 8) {
+error_report("Cannot support more than 8 threads/core "
+ "on a powernv POWER8 machine");
+exit(1);
+}
+
+pnv_init(machine);
+}
+
+static void pnv_power9_init(MachineState *machine)
+{
+if (machine->smp.threads > 8) {
+error_report("Cannot support more than 8 threads/core "
+ "on a powernv9/10 machine");
+exit(1);
+}
+
+pnv_init(machine);
+}
+
+static void pnv_power10_init(MachineState *machine)
+{
+pnv_power9_init(machine);
+}
+
 /*
  *0:21  Reserved - Read as zeros
  *   22:24  Chip ID
@@ -2423,6 +2445,7 @@ static void pnv_machine_power8_class_init(ObjectClass 
*oc, void *data)
 };
 
 mc->desc = "IBM PowerNV (Non-Virtualized) POWER8";
+mc->init = pnv_power8_init;
 mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power8_v2.0");
 compat_props_add(mc->compat_props, phb_compat, G_N_ELEMENTS(phb_compat));
 
@@ -2449,6 +2472,7 @@ static void pnv_machine_power9_class_init(ObjectClass 
*oc, void *data)
 };
 
 mc->desc = "IBM PowerNV (Non-Virtualized) POWER9";
+mc->init = pnv_power9_init;
 mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power9_v2.2");
 compat_props_add(mc->compat_props, phb_compat, G_N_ELEMENTS(phb_compat));
 
@@ -2473,6 +2497,7 @@ static void pnv_machine_p10_common_class_init(ObjectClass 
*oc, void *data)
 { TYPE_PNV_PHB_ROOT_PORT, "version", "5" },
 };
 
+mc->init = pnv_power10_init;
 mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power10_v2.0");
 compat_props_add(mc->compat_props, phb_compat, G_N_ELEMENTS(phb_compat));
 
-- 
2.43.0




[RFC PATCH 03/10] target/ppc: Improve SPR indirect registers

2024-05-26 Thread Nicholas Piggin
SPRC/SPRD were recently added to all BookS CPUs supported, but
they are only tested on POWER9 and POWER10, so restrict them to
those CPUs.

SPR indirect scratch registers presently replicated per-CPU like
SMT SPRs, but the PnvCore is a better place for them since they
are restricted to P9/P10.

Also add SPR indirect read access to core thread state for POWER9
since skiboot accesses that when booting to check for big-core
mode.

Signed-off-by: Nicholas Piggin 
---
 include/hw/ppc/pnv_core.h |  1 +
 target/ppc/cpu.h  |  3 --
 target/ppc/cpu_init.c | 21 ++--
 target/ppc/misc_helper.c  | 67 ---
 4 files changed, 46 insertions(+), 46 deletions(-)

diff --git a/include/hw/ppc/pnv_core.h b/include/hw/ppc/pnv_core.h
index f434c71547..21297262c1 100644
--- a/include/hw/ppc/pnv_core.h
+++ b/include/hw/ppc/pnv_core.h
@@ -53,6 +53,7 @@ struct PnvCore {
 uint32_t hwid;
 uint64_t hrmor;
 
+target_ulong scratch[8]; /* SCRATCH registers */
 struct pnv_tod_tbst pnv_tod_tbst;
 
 PnvChip *chip;
diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h
index 1e86658da6..dac13d4dac 100644
--- a/target/ppc/cpu.h
+++ b/target/ppc/cpu.h
@@ -1253,9 +1253,6 @@ struct CPUArchState {
 ppc_slb_t slb[MAX_SLB_ENTRIES]; /* PowerPC 64 SLB area */
 struct CPUBreakpoint *ciabr_breakpoint;
 struct CPUWatchpoint *dawr0_watchpoint;
-
-/* POWER CPU regs/state */
-target_ulong scratch[8]; /* SCRATCH registers (shared across core) */
 #endif
 target_ulong sr[32];   /* segment registers */
 uint32_t nb_BATs;  /* number of BATs */
diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c
index 01e358a4a5..ae483e20c4 100644
--- a/target/ppc/cpu_init.c
+++ b/target/ppc/cpu_init.c
@@ -5759,16 +5759,6 @@ static void register_power_common_book4_sprs(CPUPPCState 
*env)
  SPR_NOACCESS, SPR_NOACCESS,
  _read_generic, _core_write_generic,
  0x);
-spr_register_hv(env, SPR_POWER_SPRC, "SPRC",
- SPR_NOACCESS, SPR_NOACCESS,
- SPR_NOACCESS, SPR_NOACCESS,
- _read_generic, _write_sprc,
- 0x);
-spr_register_hv(env, SPR_POWER_SPRD, "SPRD",
- SPR_NOACCESS, SPR_NOACCESS,
- SPR_NOACCESS, SPR_NOACCESS,
- _read_sprd, _write_sprd,
- 0x);
 #endif
 }
 
@@ -5781,6 +5771,17 @@ static void register_power9_book4_sprs(CPUPPCState *env)
  SPR_NOACCESS, SPR_NOACCESS,
  _read_generic, _write_generic,
  KVM_REG_PPC_WORT, 0);
+/* SPRC/SPRD exist in earlier CPUs but only tested on POWER9/10 */
+spr_register_hv(env, SPR_POWER_SPRC, "SPRC",
+ SPR_NOACCESS, SPR_NOACCESS,
+ SPR_NOACCESS, SPR_NOACCESS,
+ _read_generic, _write_sprc,
+ 0x);
+spr_register_hv(env, SPR_POWER_SPRD, "SPRD",
+ SPR_NOACCESS, SPR_NOACCESS,
+ SPR_NOACCESS, SPR_NOACCESS,
+ _read_sprd, _write_sprd,
+ 0x);
 #endif
 }
 
diff --git a/target/ppc/misc_helper.c b/target/ppc/misc_helper.c
index fa47be2298..46ba3a5584 100644
--- a/target/ppc/misc_helper.c
+++ b/target/ppc/misc_helper.c
@@ -26,6 +26,7 @@
 #include "qemu/main-loop.h"
 #include "mmu-book3s-v3.h"
 #include "hw/ppc/ppc.h"
+#include "hw/ppc/pnv_core.h"
 
 #include "helper_regs.h"
 
@@ -321,11 +322,25 @@ void helper_store_sprc(CPUPPCState *env, target_ulong val)
 
 target_ulong helper_load_sprd(CPUPPCState *env)
 {
+PowerPCCPU *cpu = env_archcpu(env);
+PnvCore *pc = pnv_cpu_state(cpu)->core;
 target_ulong sprc = env->spr[SPR_POWER_SPRC];
 
-switch (sprc & 0x3c0) {
-case 0: /* SCRATCH0-7 */
-return env->scratch[(sprc >> 3) & 0x7];
+switch (sprc & 0x3e0) {
+case 0: /* SCRATCH0-3 */
+case 1: /* SCRATCH4-7 */
+return pc->scratch[(sprc >> 3) & 0x7];
+case 0x1e0: /* core thread state */
+if (env->excp_model == POWERPC_EXCP_POWER9) {
+/*
+ * Only implement for POWER9 because skiboot uses it to check
+ * big-core mode. Other bits are unimplemented so we would
+ * prefer to get unimplemented message on POWER10 if it were
+ * used.
+ */
+return 0;
+}
+/* fallthru */
 default:
 qemu_log_mask(LOG_UNIMP, "mfSPRD: Unimplemented SPRC:0x"
   TARGET_FMT_lx"\n", sprc);
@@ -334,41 +349,27 @@ target_ulong helper_load_sprd(CPUPPCState *env)
 return 0;
 }
 
-static void do_store_scratch(CPUPPCState *env, int nr, target_ulong val)
-{
-CPUState *cs = env_cpu(env);
-CPUState *ccs;
-uint32_t nr_threads = cs-

[RFC PATCH 07/10] target/ppc: Add helpers to check for SMT sibling threads

2024-05-26 Thread Nicholas Piggin
Add helpers for TCG code to determine if there are SMT siblings
sharing per-core and per-lpar registers. This simplifies the
callers and makes SMT register topology simpler to modify with
later changes.

Signed-off-by: Nicholas Piggin 
---
 target/ppc/cpu.h |  7 +++
 target/ppc/cpu_init.c|  2 +-
 target/ppc/excp_helper.c | 16 +++-
 target/ppc/misc_helper.c | 27 ++-
 target/ppc/timebase_helper.c | 20 +++-
 5 files changed, 28 insertions(+), 44 deletions(-)

diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h
index 9a89083932..8fd6ade471 100644
--- a/target/ppc/cpu.h
+++ b/target/ppc/cpu.h
@@ -1406,6 +1406,13 @@ struct CPUArchState {
 uint64_t pmu_base_time;
 };
 
+#define PPC_CPU_HAS_CORE_SIBLINGS(cs)   \
+(cs->nr_threads > 1)
+
+#define PPC_CPU_HAS_LPAR_SIBLINGS(cs)   \
+((POWERPC_CPU(cs)->env.flags & POWERPC_FLAG_SMT_1LPAR) &&   \
+ PPC_CPU_HAS_CORE_SIBLINGS(cs))
+
 #define _CORE_ID(cs)\
 (POWERPC_CPU(cs)->env.core_index)
 
diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c
index ae483e20c4..e71ee008ed 100644
--- a/target/ppc/cpu_init.c
+++ b/target/ppc/cpu_init.c
@@ -6975,7 +6975,7 @@ static void ppc_cpu_realize(DeviceState *dev, Error 
**errp)
 
 pcc->parent_realize(dev, errp);
 
-if (env_cpu(env)->nr_threads > 1) {
+if (PPC_CPU_HAS_CORE_SIBLINGS(cs)) {
 env->flags |= POWERPC_FLAG_SMT;
 }
 
diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c
index 0cd542675f..fd45da0f2b 100644
--- a/target/ppc/excp_helper.c
+++ b/target/ppc/excp_helper.c
@@ -3029,7 +3029,7 @@ void helper_book3s_msgsnd(CPUPPCState *env, target_ulong 
rb)
 brdcast = true;
 }
 
-if (cs->nr_threads == 1 || !brdcast) {
+if (!PPC_CPU_HAS_CORE_SIBLINGS(cs) || !brdcast) {
 ppc_set_irq(cpu, PPC_INTERRUPT_HDOORBELL, 1);
 return;
 }
@@ -3067,21 +3067,19 @@ void helper_book3s_msgsndp(CPUPPCState *env, 
target_ulong rb)
 CPUState *cs = env_cpu(env);
 PowerPCCPU *cpu = env_archcpu(env);
 CPUState *ccs;
-uint32_t nr_threads = cs->nr_threads;
 int ttir = rb & PPC_BITMASK(57, 63);
 
 helper_hfscr_facility_check(env, HFSCR_MSGP, "msgsndp", HFSCR_IC_MSGP);
 
-if (!(env->flags & POWERPC_FLAG_SMT_1LPAR)) {
-nr_threads = 1; /* msgsndp behaves as 1-thread in LPAR-per-thread 
mode*/
-}
-
-if (!dbell_type_server(rb) || ttir >= nr_threads) {
+if (!dbell_type_server(rb)) {
 return;
 }
 
-if (nr_threads == 1) {
-ppc_set_irq(cpu, PPC_INTERRUPT_DOORBELL, 1);
+/* msgsndp behaves as 1-thread in LPAR-per-thread mode*/
+if (!PPC_CPU_HAS_LPAR_SIBLINGS(cs)) {
+if (ttir == 0) {
+ppc_set_irq(cpu, PPC_INTERRUPT_DOORBELL, 1);
+}
 return;
 }
 
diff --git a/target/ppc/misc_helper.c b/target/ppc/misc_helper.c
index 46ba3a5584..598c956cdd 100644
--- a/target/ppc/misc_helper.c
+++ b/target/ppc/misc_helper.c
@@ -49,9 +49,8 @@ void helper_spr_core_write_generic(CPUPPCState *env, uint32_t 
sprn,
 {
 CPUState *cs = env_cpu(env);
 CPUState *ccs;
-uint32_t nr_threads = cs->nr_threads;
 
-if (nr_threads == 1) {
+if (!PPC_CPU_HAS_CORE_SIBLINGS(cs)) {
 env->spr[sprn] = val;
 return;
 }
@@ -196,7 +195,7 @@ void helper_store_ptcr(CPUPPCState *env, target_ulong val)
 return;
 }
 
-if (cs->nr_threads == 1 || !(env->flags & POWERPC_FLAG_SMT_1LPAR)) {
+if (!PPC_CPU_HAS_LPAR_SIBLINGS(cs)) {
 env->spr[SPR_PTCR] = val;
 tlb_flush(cs);
 } else {
@@ -243,16 +242,12 @@ target_ulong helper_load_dpdes(CPUPPCState *env)
 {
 CPUState *cs = env_cpu(env);
 CPUState *ccs;
-uint32_t nr_threads = cs->nr_threads;
 target_ulong dpdes = 0;
 
 helper_hfscr_facility_check(env, HFSCR_MSGP, "load DPDES", HFSCR_IC_MSGP);
 
-if (!(env->flags & POWERPC_FLAG_SMT_1LPAR)) {
-nr_threads = 1; /* DPDES behaves as 1-thread in LPAR-per-thread mode */
-}
-
-if (nr_threads == 1) {
+/* DPDES behaves as 1-thread in LPAR-per-thread mode */
+if (!PPC_CPU_HAS_LPAR_SIBLINGS(cs)) {
 if (env->pending_interrupts & PPC_INTERRUPT_DOORBELL) {
 dpdes = 1;
 }
@@ -279,21 +274,11 @@ void helper_store_dpdes(CPUPPCState *env, target_ulong 
val)
 PowerPCCPU *cpu = env_archcpu(env);
 CPUState *cs = env_cpu(env);
 CPUState *ccs;
-uint32_t nr_threads = cs->nr_threads;
 
 helper_hfscr_facility_check(env, HFSCR_MSGP, "store DPDES", HFSCR_IC_MSGP);
 
-if (!(env->flags & POWERPC_FLAG_SMT_1LPAR)) {
-nr_threads = 1; /* DPDES behaves as 1-thread in LPAR-per-thread mode */
-}
-
-if (val & ~(nr_threads - 1)

[RFC PATCH 08/10] ppc/pnv: Invert the design for big-core machine modelling

2024-05-26 Thread Nicholas Piggin
POWER9 and POWER10 machines come in two variants, "big-core" and
"small-core".

Big core machines are SMT8 from the software point of view, but in the
low level platform topology ("xscom registers and pervasive
addressing"), these look more like a pair of small cores ganged
together.

Presently, the way this is modelled is to create an SMT8 PnvCore and
add special cases to xscom and pervasive for big-core mode. This is
becoming too complicated to manage as more of the machine is modelled.
The better approach looks like the inverse, which is creating 2xPnvCore
ganging them together to look like an SMT8 core in TCG. The TCG SMT code
is quite simple to do that, and then the xscom and pervasive modelling
does not need to differentiate big and small core modes for the most
part.

device-tree building does need a special case to only build one
CPU node for each big-core because that's what the firmware expects.
And so does a special case workaround in the ChipTOD model.

A big-core machine option is added for powernv9 and 10 machines.

Signed-off-by: Nicholas Piggin 
---
 include/hw/ppc/pnv.h |   3 +
 include/hw/ppc/pnv_core.h|   8 ++
 target/ppc/cpu.h |   4 +-
 hw/ppc/pnv.c | 183 ---
 hw/ppc/pnv_core.c|  20 +++-
 hw/ppc/spapr_cpu_core.c  |   6 +-
 target/ppc/misc_helper.c |   6 +-
 target/ppc/timebase_helper.c |   9 ++
 8 files changed, 197 insertions(+), 42 deletions(-)

diff --git a/include/hw/ppc/pnv.h b/include/hw/ppc/pnv.h
index 476b136146..93ecb062b4 100644
--- a/include/hw/ppc/pnv.h
+++ b/include/hw/ppc/pnv.h
@@ -100,6 +100,9 @@ struct PnvMachineState {
 PnvPnor  *pnor;
 
 hwaddr   fw_load_addr;
+
+bool big_core;
+bool big_core_tbst_quirk;
 };
 
 PnvChip *pnv_get_chip(PnvMachineState *pnv, uint32_t chip_id);
diff --git a/include/hw/ppc/pnv_core.h b/include/hw/ppc/pnv_core.h
index 21297262c1..39f8f33e6c 100644
--- a/include/hw/ppc/pnv_core.h
+++ b/include/hw/ppc/pnv_core.h
@@ -27,6 +27,13 @@
 
 /* ChipTOD and TimeBase State Machine */
 struct pnv_tod_tbst {
+/*
+ * POWER10 DD2.0 - big core TFMR drives the state machine on the even
+ * small core. Skiboot has a workaround that targets the even small core
+ * for CHIPTOD_TO_TB ops.
+ */
+bool big_core_quirk;
+
 int tb_ready_for_tod; /* core TB ready to receive TOD from chiptod */
 int tod_sent_to_tb;   /* chiptod sent TOD to the core TB */
 
@@ -49,6 +56,7 @@ struct PnvCore {
 
 /*< public >*/
 PowerPCCPU **threads;
+bool big_core;
 uint32_t pir;
 uint32_t hwid;
 uint64_t hrmor;
diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h
index 8fd6ade471..de15e38af8 100644
--- a/target/ppc/cpu.h
+++ b/target/ppc/cpu.h
@@ -1248,6 +1248,7 @@ struct CPUArchState {
 int access_type;
 
 /* For SMT processors */
+int has_smt_siblings;
 int core_index;
 
 #if !defined(CONFIG_USER_ONLY)
@@ -1276,7 +1277,6 @@ struct CPUArchState {
 uint32_t tlb_need_flush; /* Delayed flush needed */
 #define TLB_NEED_LOCAL_FLUSH   0x1
 #define TLB_NEED_GLOBAL_FLUSH  0x2
-
 #endif
 
 /* Other registers */
@@ -1407,7 +1407,7 @@ struct CPUArchState {
 };
 
 #define PPC_CPU_HAS_CORE_SIBLINGS(cs)   \
-(cs->nr_threads > 1)
+(POWERPC_CPU(cs)->env.has_smt_siblings)
 
 #define PPC_CPU_HAS_LPAR_SIBLINGS(cs)   \
 ((POWERPC_CPU(cs)->env.flags & POWERPC_FLAG_SMT_1LPAR) &&   \
diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c
index 7d062ec16c..5364c55bbb 100644
--- a/hw/ppc/pnv.c
+++ b/hw/ppc/pnv.c
@@ -142,7 +142,7 @@ static int pnv_dt_core(PnvChip *chip, PnvCore *pc, void 
*fdt)
 CPUPPCState *env = >env;
 PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cs);
 PnvChipClass *pnv_cc = PNV_CHIP_GET_CLASS(chip);
-g_autofree uint32_t *servers_prop = g_new(uint32_t, smt_threads);
+uint32_t *servers_prop;
 int i;
 uint32_t pir, tir;
 uint32_t segs[] = {cpu_to_be32(28), cpu_to_be32(40),
@@ -157,6 +157,14 @@ static int pnv_dt_core(PnvChip *chip, PnvCore *pc, void 
*fdt)
 
 pnv_cc->processor_id(chip, pc->hwid, 0, , );
 
+/* Only one DT node per (big) core */
+if (tir != 0) {
+g_assert(pc->big_core);
+g_assert(tir == 1);
+g_assert(pc->hwid & 1);
+return -1;
+}
+
 nodename = g_strdup_printf("%s@%x", dc->fw_name, pir);
 offset = fdt_add_subnode(fdt, cpus_offset, nodename);
 _FDT(offset);
@@ -236,12 +244,28 @@ static int pnv_dt_core(PnvChip *chip, PnvCore *pc, void 
*fdt)
 }
 
 /* Build interrupt servers properties */
-for (i = 0; i < smt_threads; i++) {
-pnv_cc->processor_id(chip, pc->hwid, i, , );
-servers_prop[i] = cpu_to_be32(pir);
+if (pc->big_core) {
+servers_prop = g_new(uint32_t, smt_threads * 2);
+for (i = 0; i <

[RFC PATCH 02/10] ppc/pnv: Move timebase state into PnvCore

2024-05-26 Thread Nicholas Piggin
The timebase state machine is per per-core state and can be driven
by any thread in the core. It is currently implemented as a hack
where the state is in a CPU structure and only thread 0's state is
accessed by the chiptod, which limits programming the timebase
side of the state machine to thread 0 of a core.

Move the state out into PnvCore and share it among all threads.

Signed-off-by: Nicholas Piggin 
---
 include/hw/ppc/pnv_core.h| 17 
 target/ppc/cpu.h | 20 --
 hw/ppc/pnv_chiptod.c |  6 ++--
 target/ppc/timebase_helper.c | 53 
 4 files changed, 49 insertions(+), 47 deletions(-)

diff --git a/include/hw/ppc/pnv_core.h b/include/hw/ppc/pnv_core.h
index 30c1e5b1a3..f434c71547 100644
--- a/include/hw/ppc/pnv_core.h
+++ b/include/hw/ppc/pnv_core.h
@@ -25,6 +25,20 @@
 #include "hw/ppc/pnv.h"
 #include "qom/object.h"
 
+/* ChipTOD and TimeBase State Machine */
+struct pnv_tod_tbst {
+int tb_ready_for_tod; /* core TB ready to receive TOD from chiptod */
+int tod_sent_to_tb;   /* chiptod sent TOD to the core TB */
+
+/*
+ * "Timers" for async TBST events are simulated by mfTFAC because TFAC
+ * is polled for such events. These are just used to ensure firmware
+ * performs the polling at least a few times.
+ */
+int tb_state_timer;
+int tb_sync_pulse_timer;
+};
+
 #define TYPE_PNV_CORE "powernv-cpu-core"
 OBJECT_DECLARE_TYPE(PnvCore, PnvCoreClass,
 PNV_CORE)
@@ -38,6 +52,9 @@ struct PnvCore {
 uint32_t pir;
 uint32_t hwid;
 uint64_t hrmor;
+
+struct pnv_tod_tbst pnv_tod_tbst;
+
 PnvChip *chip;
 
 MemoryRegion xscom_regs;
diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h
index 2015e603d4..1e86658da6 100644
--- a/target/ppc/cpu.h
+++ b/target/ppc/cpu.h
@@ -1196,21 +1196,6 @@ DEXCR_ASPECT(SRAPD, 4)
 DEXCR_ASPECT(NPHIE, 5)
 DEXCR_ASPECT(PHIE, 6)
 
-/*/
-/* PowerNV ChipTOD and TimeBase State Machine */
-struct pnv_tod_tbst {
-int tb_ready_for_tod; /* core TB ready to receive TOD from chiptod */
-int tod_sent_to_tb;   /* chiptod sent TOD to the core TB */
-
-/*
- * "Timers" for async TBST events are simulated by mfTFAC because TFAC
- * is polled for such events. These are just used to ensure firmware
- * performs the polling at least a few times.
- */
-int tb_state_timer;
-int tb_sync_pulse_timer;
-};
-
 /*/
 /* The whole PowerPC CPU context */
 
@@ -1292,11 +1277,6 @@ struct CPUArchState {
 #define TLB_NEED_LOCAL_FLUSH   0x1
 #define TLB_NEED_GLOBAL_FLUSH  0x2
 
-#if defined(TARGET_PPC64)
-/* PowerNV chiptod / timebase facility state. */
-/* Would be nice to put these into PnvCore */
-struct pnv_tod_tbst pnv_tod_tbst;
-#endif
 #endif
 
 /* Other registers */
diff --git a/hw/ppc/pnv_chiptod.c b/hw/ppc/pnv_chiptod.c
index 3831a72101..3eaddd66f0 100644
--- a/hw/ppc/pnv_chiptod.c
+++ b/hw/ppc/pnv_chiptod.c
@@ -365,7 +365,7 @@ static void pnv_chiptod_xscom_write(void *opaque, hwaddr 
addr,
   " TOD_MOVE_TOD_TO_TB_REG with no slave target\n");
 } else {
 PowerPCCPU *cpu = chiptod->slave_pc_target->threads[0];
-CPUPPCState *env = >env;
+PnvCore *pc = pnv_cpu_state(cpu)->core;
 
 /*
  * Moving TOD to TB will set the TB of all threads in a
@@ -377,8 +377,8 @@ static void pnv_chiptod_xscom_write(void *opaque, hwaddr 
addr,
  * thread 0.
  */
 
-if (env->pnv_tod_tbst.tb_ready_for_tod) {
-env->pnv_tod_tbst.tod_sent_to_tb = 1;
+if (pc->pnv_tod_tbst.tb_ready_for_tod) {
+pc->pnv_tod_tbst.tod_sent_to_tb = 1;
 } else {
 qemu_log_mask(LOG_GUEST_ERROR, "pnv_chiptod: xscom write reg"
   " TOD_MOVE_TOD_TO_TB_REG with TB not ready to"
diff --git a/target/ppc/timebase_helper.c b/target/ppc/timebase_helper.c
index 39d397416e..788c498d63 100644
--- a/target/ppc/timebase_helper.c
+++ b/target/ppc/timebase_helper.c
@@ -19,6 +19,7 @@
 #include "qemu/osdep.h"
 #include "cpu.h"
 #include "hw/ppc/ppc.h"
+#include "hw/ppc/pnv_core.h"
 #include "exec/helper-proto.h"
 #include "exec/exec-all.h"
 #include "qemu/log.h"
@@ -298,8 +299,17 @@ static void write_tfmr(CPUPPCState *env, target_ulong val)
 }
 }
 
+static struct pnv_tod_tbst *cpu_get_tbst(PowerPCCPU *cpu)
+{
+PnvCore *pc = pnv_cpu_state(cpu)->core;
+
+return >pnv_tod_tbst;
+}
+
 static void tb_state_machine_step(CPUPPCState *env)
 {
+PowerPCCPU *cpu = env_archcpu(env);
+struct pnv_tod_tbst *pnv_tod_tbst = cpu_

[RFC PATCH 10/10] ppc/pnv: Add an LPAR per core machine option

2024-05-26 Thread Nicholas Piggin
Recent POWER CPUs can operate in "LPAR per core" or "LPAR per thread"
modes. In per-core mode, some SPRs and IPI doorbells are shared between
threads in a core. In per-thread mode, supervisor and user state is
not shared between threads.

OpenPOWER systems use LPAR per thread mode as it is required for KVM.
Enterprise systems use LPAR per core mode, as they partition the
machine by core.

Implement a lpar-per-core machine option for powernv machines. This
is supported on POWER9 and POWER10.

Signed-off-by: Nicholas Piggin 
---
 include/hw/ppc/pnv.h  |  1 +
 include/hw/ppc/pnv_core.h |  1 +
 hw/ppc/pnv.c  | 29 +
 hw/ppc/pnv_core.c |  8 
 target/ppc/cpu_init.c |  3 ++-
 5 files changed, 41 insertions(+), 1 deletion(-)

diff --git a/include/hw/ppc/pnv.h b/include/hw/ppc/pnv.h
index bec603f1a8..8f75c715d8 100644
--- a/include/hw/ppc/pnv.h
+++ b/include/hw/ppc/pnv.h
@@ -103,6 +103,7 @@ struct PnvMachineState {
 
 bool big_core;
 bool big_core_tbst_quirk;
+bool lpar_per_core;
 };
 
 PnvChip *pnv_get_chip(PnvMachineState *pnv, uint32_t chip_id);
diff --git a/include/hw/ppc/pnv_core.h b/include/hw/ppc/pnv_core.h
index 9599da15ea..e41b6347ea 100644
--- a/include/hw/ppc/pnv_core.h
+++ b/include/hw/ppc/pnv_core.h
@@ -57,6 +57,7 @@ struct PnvCore {
 /*< public >*/
 PowerPCCPU **threads;
 bool big_core;
+bool lpar_per_core;
 uint32_t pir;
 uint32_t hwid;
 uint64_t hrmor;
diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c
index 765142965f..0d830ad731 100644
--- a/hw/ppc/pnv.c
+++ b/hw/ppc/pnv.c
@@ -1108,12 +1108,17 @@ static void pnv_init(MachineState *machine)
 
 static void pnv_power8_init(MachineState *machine)
 {
+PnvMachineState *pnv = PNV_MACHINE(machine);
+
 if (machine->smp.threads > 8) {
 error_report("Cannot support more than 8 threads/core "
  "on a powernv POWER8 machine");
 exit(1);
 }
 
+/* POWER8 is always lpar-per-core. */
+pnv->lpar_per_core = true;
+
 pnv_init(machine);
 }
 
@@ -2541,6 +2546,18 @@ static void pnv_machine_set_big_core(Object *obj, bool 
value, Error **errp)
 pnv->big_core = value;
 }
 
+static bool pnv_machine_get_1lpar(Object *obj, Error **errp)
+{
+PnvMachineState *pnv = PNV_MACHINE(obj);
+return pnv->lpar_per_core;
+}
+
+static void pnv_machine_set_1lpar(Object *obj, bool value, Error **errp)
+{
+PnvMachineState *pnv = PNV_MACHINE(obj);
+pnv->lpar_per_core = value;
+}
+
 static bool pnv_machine_get_hb(Object *obj, Error **errp)
 {
 PnvMachineState *pnv = PNV_MACHINE(obj);
@@ -2614,6 +2631,12 @@ static void pnv_machine_power9_class_init(ObjectClass 
*oc, void *data)
pnv_machine_set_big_core);
 object_class_property_set_description(oc, "big-core",
   "Use big-core (aka fused-core) mode");
+
+object_class_property_add_bool(oc, "lpar-per-core",
+   pnv_machine_get_1lpar,
+   pnv_machine_set_1lpar);
+object_class_property_set_description(oc, "lpar-per-core",
+  "Use 1 LPAR per core mode");
 }
 
 static void pnv_machine_p10_common_class_init(ObjectClass *oc, void *data)
@@ -2660,6 +2683,12 @@ static void pnv_machine_power10_class_init(ObjectClass 
*oc, void *data)
pnv_machine_set_big_core);
 object_class_property_set_description(oc, "big-core",
   "Use big-core (aka fused-core) mode");
+
+object_class_property_add_bool(oc, "lpar-per-core",
+   pnv_machine_get_1lpar,
+   pnv_machine_set_1lpar);
+object_class_property_set_description(oc, "lpar-per-core",
+  "Use 1 LPAR per core mode");
 }
 
 static void pnv_machine_p10_rainier_class_init(ObjectClass *oc, void *data)
diff --git a/hw/ppc/pnv_core.c b/hw/ppc/pnv_core.c
index 835c35d90b..e510909db1 100644
--- a/hw/ppc/pnv_core.c
+++ b/hw/ppc/pnv_core.c
@@ -207,6 +207,9 @@ static uint64_t pnv_core_power10_xscom_read(void *opaque, 
hwaddr addr,
 val |= PPC_BIT(56 + i);
 }
 }
+if (pc->lpar_per_core) {
+val |= PPC_BIT(62);
+}
 break;
 case PNV10_XSCOM_EC_CORE_THREAD_INFO:
 break;
@@ -322,6 +325,11 @@ static void pnv_core_cpu_realize(PnvCore *pc, PowerPCCPU 
*cpu, Error **errp,
 env->core_index = core_hwid;
 }
 
+if (pnv->lpar_per_core) {
+pc->lpar_per_core = true;
+cpu_ppc_set_1lpar(cpu);
+}
+
 /* Set time-base frequency to 512 MHz */
 cpu_ppc_tb_init(env, PNV_TIMEBASE_FREQ);
 }
diff --git a/target/ppc/cpu_init.c 

[RFC PATCH 1/3] hw/intc/s390_flic: Migrate pending state

2024-05-25 Thread Nicholas Piggin
The flic pending state is not migrated, so if the machine is migrated
while an interrupt is pending, it can be lost. This shows up in
qtest migration test, an extint is pending (due to console writes?)
and the CPU waits via s390_cpu_set_psw and expects the interrupt to
wake it. However when the flic pending state is lost, s390_cpu_has_int
returns false, so s390_cpu_exec_interrupt falls through to halting
again.

Fix this by migrating pending. This prevents the qtest from hanging.
Does service_param need to be migrated? Or the IO lists?

Signed-off-by: Nicholas Piggin 
---
 hw/intc/s390_flic.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/hw/intc/s390_flic.c b/hw/intc/s390_flic.c
index 6771645699..b70cf2295a 100644
--- a/hw/intc/s390_flic.c
+++ b/hw/intc/s390_flic.c
@@ -369,6 +369,7 @@ static const VMStateDescription qemu_s390_flic_vmstate = {
 .fields = (const VMStateField[]) {
 VMSTATE_UINT8(simm, QEMUS390FLICState),
 VMSTATE_UINT8(nimm, QEMUS390FLICState),
+VMSTATE_UINT32(pending, QEMUS390FLICState),
 VMSTATE_END_OF_LIST()
 }
 };
-- 
2.43.0




[RFC PATCH 3/3] tests/qtest/migration-test: Enable test_ignore_shared

2024-05-25 Thread Nicholas Piggin
This was said to be broken on aarch64, but if it works on others,
let's try enable it. It's already starting to bitrot...

Cc: Yury Kotov 
Cc: Dr. David Alan Gilbert 
Signed-off-by: Nicholas Piggin 
---
 tests/qtest/migration-test.c | 13 -
 1 file changed, 8 insertions(+), 5 deletions(-)

diff --git a/tests/qtest/migration-test.c b/tests/qtest/migration-test.c
index 7987faaded..2bcdc33b7c 100644
--- a/tests/qtest/migration-test.c
+++ b/tests/qtest/migration-test.c
@@ -1862,14 +1862,15 @@ static void 
test_precopy_unix_tls_x509_override_host(void)
 #endif /* CONFIG_TASN1 */
 #endif /* CONFIG_GNUTLS */
 
-#if 0
-/* Currently upset on aarch64 TCG */
 static void test_ignore_shared(void)
 {
 g_autofree char *uri = g_strdup_printf("unix:%s/migsocket", tmpfs);
 QTestState *from, *to;
+MigrateStart args = {
+.use_shmem = true,
+};
 
-if (test_migrate_start(, , uri, false, true, NULL, NULL)) {
+if (test_migrate_start(, , uri, )) {
 return;
 }
 
@@ -1898,7 +1899,6 @@ static void test_ignore_shared(void)
 
 test_migrate_end(from, to, true);
 }
-#endif
 
 static void *
 test_migrate_xbzrle_start(QTestState *from,
@@ -3537,7 +3537,10 @@ int main(int argc, char **argv)
 #endif /* CONFIG_TASN1 */
 #endif /* CONFIG_GNUTLS */
 
-/* migration_test_add("/migration/ignore_shared", test_ignore_shared); */
+if (strcmp(arch, "aarch64") == 0) { /* Currently upset on aarch64 TCG */
+migration_test_add("/migration/ignore_shared", test_ignore_shared);
+}
+
 #ifndef _WIN32
 migration_test_add("/migration/precopy/fd/tcp",
test_migrate_precopy_fd_socket);
-- 
2.43.0




[RFC PATCH 0/3] Fix s390x flic migration and add some more qtests

2024-05-25 Thread Nicholas Piggin
I don't know s390x enough to know if this is the right fix, but I
could debug the migration hangs this far at least (and the patch
fixes the condition that would previously result in a hang on the
qtest).

Also we could enable the test_ignore_shared test that seems to work
on s390x and ppc64 at least.

Thanks,
Nick

Nicholas Piggin (3):
  hw/intc/s390_flic: Migrate pending state
  tests/qtest/migration-test: enable on s390x
  tests/qtest/migration-test: Enable test_ignore_shared

 hw/intc/s390_flic.c  |  1 +
 tests/qtest/migration-test.c | 25 -
 2 files changed, 9 insertions(+), 17 deletions(-)

-- 
2.43.0




[RFC PATCH 2/3] tests/qtest/migration-test: enable on s390x

2024-05-25 Thread Nicholas Piggin
s390x is more stable now. Enable it.

Signed-off-by: Nicholas Piggin 
---
 tests/qtest/migration-test.c | 12 
 1 file changed, 12 deletions(-)

diff --git a/tests/qtest/migration-test.c b/tests/qtest/migration-test.c
index 94d5057857..7987faaded 100644
--- a/tests/qtest/migration-test.c
+++ b/tests/qtest/migration-test.c
@@ -3428,16 +3428,6 @@ int main(int argc, char **argv)
 migration_test_add("/migration/analyze-script", test_analyze_script);
 #endif
 
-/*
- * On s390x, the test seems to be touchy with TCG, perhaps due to race
- * conditions on dirty bits, so disable it there until the problems are
- * resolved.
- */
-if (g_str_equal(arch, "s390x") && !has_kvm) {
-g_test_message("Skipping tests: s390x host with KVM is required");
-goto test_add_done;
-}
-
 if (is_x86) {
 migration_test_add("/migration/precopy/unix/suspend/live",
test_precopy_unix_suspend_live);
@@ -3619,8 +3609,6 @@ int main(int argc, char **argv)
test_vcpu_dirty_limit);
 }
 
-test_add_done:
-
 ret = g_test_run();
 
 g_assert_cmpint(ret, ==, 0);
-- 
2.43.0




[PATCH 3/3] tests/qtest/migration-test: Use custom asm bios for ppc64

2024-05-24 Thread Nicholas Piggin
Similar to other archs, build a custom bios memory updater. Running the
test with OF code is a cool trick, but SLOF takes a long time to boot.
This reduces test time by around 3x (150s to 50s).

Signed-off-by: Nicholas Piggin 
---
 tests/migration/migration-test.h   |  1 +
 tests/migration/ppc64/a-b-kernel.h | 42 +++
 tests/qtest/migration-test.c   | 35 +++-
 tests/migration/Makefile   |  2 +-
 tests/migration/ppc64/Makefile | 15 +++
 tests/migration/ppc64/a-b-kernel.S | 66 ++
 6 files changed, 130 insertions(+), 31 deletions(-)
 create mode 100644 tests/migration/ppc64/a-b-kernel.h
 create mode 100644 tests/migration/ppc64/Makefile
 create mode 100644 tests/migration/ppc64/a-b-kernel.S

diff --git a/tests/migration/migration-test.h b/tests/migration/migration-test.h
index 68512c0b1b..194df7df6f 100644
--- a/tests/migration/migration-test.h
+++ b/tests/migration/migration-test.h
@@ -22,6 +22,7 @@
 /* PPC */
 #define PPC_TEST_MEM_START (1 * 1024 * 1024)
 #define PPC_TEST_MEM_END   (100 * 1024 * 1024)
+#define PPC_H_PUT_TERM_CHAR 0x58
 
 /* ARM */
 #define ARM_TEST_MEM_START (0x4000 + 1 * 1024 * 1024)
diff --git a/tests/migration/ppc64/a-b-kernel.h 
b/tests/migration/ppc64/a-b-kernel.h
new file mode 100644
index 00..673317efdb
--- /dev/null
+++ b/tests/migration/ppc64/a-b-kernel.h
@@ -0,0 +1,42 @@
+/* This file is automatically generated from the assembly file in
+ * tests/migration/ppc64. 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 ppc64_kernel[] = {
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x7d, 0x20, 0x00, 0xa6, 0x39, 0x40, 0xff, 0xff,
+  0x79, 0x49, 0xf8, 0x0e, 0x7d, 0x20, 0x01, 0x64, 0x3e, 0x80, 0x00, 0x10,
+  0x62, 0x94, 0x00, 0x00, 0x3d, 0x20, 0x06, 0x40, 0x61, 0x29, 0x00, 0x00,
+  0x7e, 0xb4, 0x48, 0x50, 0x39, 0x40, 0x10, 0x00, 0x7e, 0xb5, 0x53, 0xd2,
+  0x38, 0x60, 0x00, 0x58, 0x38, 0x80, 0x00, 0x00, 0x38, 0xa0, 0x00, 0x01,
+  0x38, 0xc0, 0x00, 0x41, 0x78, 0xc6, 0xc1, 0xc6, 0x44, 0x00, 0x00, 0x22,
+  0x38, 0x60, 0x00, 0x00, 0x7e, 0x89, 0xa3, 0x78, 0x7e, 0xa9, 0x03, 0xa6,
+  0x98, 0x69, 0x00, 0x00, 0x39, 0x29, 0x10, 0x00, 0x42, 0x00, 0xff, 0xf8,
+  0x7e, 0x89, 0xa3, 0x78, 0x7e, 0xa9, 0x03, 0xa6, 0x88, 0x69, 0x00, 0x00,
+  0x38, 0x63, 0x00, 0x01, 0x98, 0x69, 0x00, 0x00, 0x39, 0x29, 0x10, 0x00,
+  0x42, 0x00, 0xff, 0xf0, 0x38, 0x60, 0x00, 0x58, 0x38, 0x80, 0x00, 0x00,
+  0x38, 0xa0, 0x00, 0x01, 0x38, 0xc0, 0x00, 0x42, 0x78, 0xc6, 0xc1, 0xc6,
+  0x44, 0x00, 0x00, 0x22, 0x4b, 0xff, 0xff, 0xcc
+};
+
diff --git a/tests/qtest/migration-test.c b/tests/qtest/migration-test.c
index b8617cc843..94d5057857 100644
--- a/tests/qtest/migration-test.c
+++ b/tests/qtest/migration-test.c
@@ -128,6 +128,7 @@ static char *bootpath;
  */
 #include "tests/migration/i386/a-b-bootblock.h"
 #include "tests/migration/aarch64/a-b-kernel.h"
+#include "tests/migration/ppc64/a-b-kernel.h"
 #include "tests/migration/s390x/a-b-bios.h"
 
 static void bootfile_create(char *dir, bool suspend_me)
@@ -147,10 +148,8 @@ static void bootfile_create(char *dir, bool suspend_me)
 content = s390x_elf;
 len = sizeof(s390x_elf);
 } else if (strcmp(arch, "ppc64") == 0) {
-/*
-  

[PATCH 2/3] tests/qtest/migration-test: Enable on ppc64

2024-05-24 Thread Nicholas Piggin
ppc64 with TCG seems to no longer be failing this test. Let's try to
enable it. s390x is still hanging about 1 in 10 runs.

Signed-off-by: Nicholas Piggin 
---
 tests/qtest/migration-test.c | 16 +++-
 1 file changed, 3 insertions(+), 13 deletions(-)

diff --git a/tests/qtest/migration-test.c b/tests/qtest/migration-test.c
index c13535c37d..b8617cc843 100644
--- a/tests/qtest/migration-test.c
+++ b/tests/qtest/migration-test.c
@@ -3454,19 +3454,9 @@ int main(int argc, char **argv)
 #endif
 
 /*
- * On ppc64, the test only works with kvm-hv, but not with kvm-pr and TCG
- * is touchy due to race conditions on dirty bits (especially on PPC for
- * some reason)
- */
-if (g_str_equal(arch, "ppc64") &&
-(!has_kvm || access("/sys/module/kvm_hv", F_OK))) {
-g_test_message("Skipping tests: kvm_hv not available");
-goto test_add_done;
-}
-
-/*
- * Similar to ppc64, s390x seems to be touchy with TCG, so disable it
- * there until the problems are resolved
+ * On s390x, the test seems to be touchy with TCG, perhaps due to race
+ * conditions on dirty bits, so disable it there until the problems are
+ * resolved.
  */
 if (g_str_equal(arch, "s390x") && !has_kvm) {
 g_test_message("Skipping tests: s390x host with KVM is required");
-- 
2.43.0




[PATCH 1/3] tests/qtest/migration-test: Quieten ppc64 QEMU warnigns

2024-05-24 Thread Nicholas Piggin
Signed-off-by: Nicholas Piggin 
---
 tests/qtest/migration-test.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/tests/qtest/migration-test.c b/tests/qtest/migration-test.c
index b7e3406471..c13535c37d 100644
--- a/tests/qtest/migration-test.c
+++ b/tests/qtest/migration-test.c
@@ -21,6 +21,7 @@
 #include "chardev/char.h"
 #include "crypto/tlscredspsk.h"
 #include "qapi/qmp/qlist.h"
+#include "libqos/libqos-spapr.h"
 
 #include "migration-helpers.h"
 #include "tests/migration/migration-test.h"
@@ -742,7 +743,8 @@ static int test_migrate_start(QTestState **from, QTestState 
**to,
   "until'", end_address, start_address);
 machine_alias = "pseries";
 machine_opts = "vsmt=8";
-arch_opts = g_strdup("-nodefaults");
+arch_opts = g_strdup_printf("-nodefaults "
+"-machine " PSERIES_DEFAULT_CAPABILITIES);
 } else if (strcmp(arch, "aarch64") == 0) {
 memory_size = "150M";
 machine_alias = "virt";
-- 
2.43.0




[PATCH 0/3] tests/qtest/migration-test: Improve and enable on ppc64

2024-05-24 Thread Nicholas Piggin
ppc64 seems to be stable now, only problem is the speed, so I
rewrote the test to avoid SLOF and use special bios blob like
the other archs.

Thanks,
Nick

Nicholas Piggin (3):
  tests/qtest/migration-test: Quieten ppc64 QEMU warnigns
  tests/qtest/migration-test: Enable on ppc64
  tests/qtest/migration-test: Use custom asm bios for ppc64

 tests/migration/migration-test.h   |  1 +
 tests/migration/ppc64/a-b-kernel.h | 42 +++
 tests/qtest/migration-test.c   | 53 +---
 tests/migration/Makefile   |  2 +-
 tests/migration/ppc64/Makefile | 15 +++
 tests/migration/ppc64/a-b-kernel.S | 66 ++
 6 files changed, 135 insertions(+), 44 deletions(-)
 create mode 100644 tests/migration/ppc64/a-b-kernel.h
 create mode 100644 tests/migration/ppc64/Makefile
 create mode 100644 tests/migration/ppc64/a-b-kernel.S

-- 
2.43.0




Re: [PATCH] tests/qtest/migration-test: Run some basic tests on s390x and ppc64 with TCG, too

2024-05-23 Thread Nicholas Piggin
On Wed May 22, 2024 at 7:12 PM AEST, Thomas Huth wrote:
> On s390x, we recently had a regression that broke migration / savevm
> (see commit bebe9603fc ("hw/intc/s390_flic: Fix crash that occurs when
> saving the machine state"). The problem was merged without being noticed
> since we currently do not run any migration / savevm related tests on
> x86 hosts.
> While we currently cannot run all migration tests for the s390x target
> on x86 hosts yet (due to some unresolved issues with TCG), we can at
> least run some of the non-live tests to avoid such problems in the future.
> Thus enable the "analyze-script" and the "bad_dest" tests before checking
> for KVM on s390x or ppc64 (this also fixes the problem that the
> "analyze-script" test was not run on s390x at all anymore since it got
> disabled again by accident in a previous refactoring of the code).

ppc64 is working for me, can it be enabled fully, or is it still
breaking somewhere? FWIW I have a patch to change it from using
open-firmware commands to a boot file which speeds it up.

Would be nice to get to the bottom of the s390x problem too :(

Thanks,
Nick



[PULL 00/72] ppc-for-9.1-1 queue

2024-05-23 Thread Nicholas Piggin
This replaces the previous PR for tags/pull-ppc-for-9.1-1-20240524 note
this tag is tags/pull-ppc-for-9.1-1-20240524-1 (added -1 suffix). The
changelog and code are unchanged. Subject for BHRB patches are fixed
and trimmed for some MMU cleanup patches. So I won't re-send individual
patches to lists.

Thanks,
Nick

The following changes since commit 70581940cabcc51b329652becddfbc6a261b1b83:

  Merge tag 'pull-tcg-20240523' of https://gitlab.com/rth7680/qemu into staging 
(2024-05-23 09:47:40 -0700)

are available in the Git repository at:

  https://gitlab.com/npiggin/qemu.git tags/pull-ppc-for-9.1-1-20240524-1

for you to fetch changes up to e48fb4c590a23d81ee1d2f09ee9bcf5dd5f98e43:

  target/ppc: Remove pp_check() and reuse ppc_hash32_pp_prot() (2024-05-24 
09:43:14 +1000)



* Fix an interesting TLB invalidate race
* Implement more instructions with decodetree
* Add the POWER8/9/10 BHRB facility
* Add missing instructions, registers, SMT support
* First round of a big MMU xlate cleanup


BALATON Zoltan (33):
  target/ppc: Remove unused helper_rac()
  target/ppc: Move calculation of a value closer to its usage in booke tlb 
checks
  target/ppc: Remove unneeded local variable from booke tlb checks
  target/ppc: Simplify checking for real mode in get_physical_address_wtlb()
  target/ppc: Drop cases for unimplemented MPC8xx MMU
  target/ppc: Introduce mmu6xx_get_physical_address()
  target/ppc: Move else branch to avoid large if block in 
mmu6xx_get_physical_address()
  target/ppc: Move some debug logging in ppc6xx_tlb_check()
  target/ppc: Eliminate ret from mmu6xx_get_physical_address()
  target/ppc: Split out BookE xlate cases before checking real mode
  target/ppc: Split off real mode cases in get_physical_address_wtlb()
  target/ppc: Inline and remove check_physical()
  target/ppc: Fix misindented qemu_log_mask() calls
  target/ppc: Deindent ppc_jumbo_xlate()
  target/ppc: Replace hard coded constants in ppc_jumbo_xlate()
  target/ppc: Don't use mmu_ctx_t for mmu40x_get_physical_address()
  target/ppc: Don't use mmu_ctx_t in mmubooke_get_physical_address()
  target/ppc: Don't use mmu_ctx_t in mmubooke206_get_physical_address()
  target/ppc: Remove BookE from direct store handling
  target/ppc: Split off BookE handling from ppc_jumbo_xlate()
  target/ppc: Simplify ppc_booke_xlate() part 1
  target/ppc: Simplify ppc_booke_xlate() part 2
  target/ppc: Split off real mode handling from get_physical_address_wtlb()
  target/ppc: Split off 40x cases from ppc_jumbo_xlate()
  target/ppc: Transform ppc_jumbo_xlate() into ppc_6xx_xlate()
  target/ppc: Move mmu_ctx_t type to mmu_common.c
  target/ppc: Remove id_tlbs flag from CPU env
  target/ppc: Split off common embedded TLB init
  target/ppc/mmu-hash32.c: Drop a local variable
  target/ppc/mmu-radix64.c: Drop a local variable
  target/ppc: Add a function to check for page protection bit
  target/ppc: Move out BookE and related MMU functions from mmu_common.c
  target/ppc: Remove pp_check() and reuse ppc_hash32_pp_prot()

Chinmay Rath (13):
  target/ppc: Merge various fpu helpers
  target/ppc: Move floating-point arithmetic instructions to decodetree.
  target/ppc: Move mul{li, lw, lwo, hw, hwu} instructions to decodetree.
  target/ppc: Make divw[u] handler method decodetree compatible.
  target/ppc: Move divw[u, e, eu] instructions to decodetree.
  target/ppc: Move neg, darn, mod{sw, uw} to decodetree.
  target/ppc: Move multiply fixed-point insns (64-bit operands) to 
decodetree.
  target/ppc: Move div/mod fixed-point insns (64 bits operands) to 
decodetree.
  target/ppc: Move cmp{rb, eqb}, tw[i], td[i], isel instructions to 
decodetree.
  target/ppc: Move logical fixed-point instructions to decodetree.
  target/ppc: Move VMX storage access instructions to decodetree
  target/ppc: Move VMX integer logical instructions to decodetree.
  target/ppc: Move VMX integer max/min instructions to decodetree.

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

Glenn Miles (4):
  target/ppc: Add new hflags to support BHRB
  target/ppc: Add recording of taken branches to BHRB
  target/ppc: Add clrbhrb and mfbhrbe instructions
  target/ppc: Add migration support for BHRB

Nicholas Piggin (21):
  spapr: avoid overhead of finding vhyp class in critical operations
  ppc/spapr: Add ibm,pi-features
  target/ppc: Fix broadcast tlbie synchronisation
  tcg/cputlb: Remove non-synced variants of global TLB flushes
  tcg/cputlb: remove other-cpu capability from TLB flushing
  target/ppc: Move sync instructions to decodetree
  target/ppc: Fix embedded memory barriers
  target/ppc: Add ISA v3.1

Re: [PULL 00/72] ppc-for-9.1-1 queue

2024-05-23 Thread Nicholas Piggin
On Fri May 24, 2024 at 9:06 AM AEST, Nicholas Piggin wrote:
> The following changes since commit 70581940cabcc51b329652becddfbc6a261b1b83:
>
>   Merge tag 'pull-tcg-20240523' of https://gitlab.com/rth7680/qemu into 
> staging (2024-05-23 09:47:40 -0700)
>
> are available in the Git repository at:
>
>   https://gitlab.com/npiggin/qemu.git tags/pull-ppc-for-9.1-1-20240524

[snip]

> Glenn Miles (4):
>   This commit is preparatory to the addition of Branch History Rolling 
> Buffer (BHRB) functionality, which is being provided today starting with the 
> P8 processor.
>   This commit continues adding support for the Branch History Rolling 
> Buffer (BHRB) as is provided starting with the P8 processor and continuing 
> with its successors.  This commit is limited to the recording and filtering 
> of taken branches.
>   Add support for the clrbhrb and mfbhrbe instructions.
>   Adds migration support for Branch History Rolling Buffer (BHRB) 
> internal state.

The BHRB patch subject lines have gone haywire and I didn't notice
before now. Probably my fault. Hold off and I will fix and give a
new tag to pull.

Thanks,
Nick



Re: [PATCH 0/2] target/ppc: Fix PMU instruction counting

2024-05-23 Thread Nicholas Piggin
On Thu May 23, 2024 at 8:46 AM AEST, Richard Henderson wrote:
> On 5/21/24 21:04, Nicholas Piggin wrote:
> > The crux of the problem being that dynamic exits from a TB would
> > not count instructions previously executed in the TB. I don't
> > know how important it is for PMU to count instructions exactly,
> > however for instruction replay this can lead to different counts
> > for the same execution (e.g., because TBs can be different sized)
> > and that blows up reverse debugging.
> > 
> > I posted something on this out before, but missed a few things
> > (most notably faulting memory access). And found that forcing 1
> > insn per TB seems to be the only feasible way to do this.
> > 
> > Sorry to ping you on this again Richard, it's not urgent but
> > you're the guru with this stuff and I'm hesitant to change it
> > without a better opinion ... Simple band aid for the meanwhile
> > could be leave it as is but just disable counting if
> > record/replay is in use.
>
> When we unwind, we know how many insns remain in the tb.
> With icount, we adjust cpu->neg.icount_decr.u16.low.
>
> My suggestion is to change restore_state_to_opc to pass in either the raw 
> insns_left, or 
> the inverse: tb->icount - insns_left.
>
> That'll be a trivial mechanical change for the signature of the hook, first.

That gives me a better place to start looking.

Thanks,
Nick



[PULL 62/72] target/ppc/mmu_common.c: Split off real mode handling from get_physical_address_wtlb()

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

Add ppc_real_mode_xlate() to handle real mode translation and allow
removing this case from ppc_jumbo_xlate().

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

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




[PULL 17/72] target/ppc: Move cmp{rb, eqb}, tw[i], td[i], isel instructions to decodetree.

2024-05-23 Thread Nicholas Piggin
From: Chinmay Rath 

Moving the following instructions to decodetree specification :

cmp{rb, eqb}, t{w, d}   : X-form
t{w, d}i: D-form
isel: A-form

The changes were verified by validating that the tcg ops generated by those
instructions remain the same, which were captured using the '-d in_asm,op' flag.
Also for CMPRB, following review comments :
Replaced repetition of arithmetic right shifting (tcg_gen_shri_i32) followed
by extraction of last 8 bits (tcg_gen_ext8u_i32) with extraction of the required
bits using offsets (tcg_gen_extract_i32).

Reviewed-by: Richard Henderson 
Signed-off-by: Chinmay Rath 
[np: 32-bit compile fix]
Signed-off-by: Nicholas Piggin 
---
 target/ppc/excp_helper.c   |   4 +-
 target/ppc/helper.h|   6 +-
 target/ppc/insn32.decode   |  16 +++
 target/ppc/int_helper.c|   2 +-
 target/ppc/translate.c | 133 +
 target/ppc/translate/fixedpoint-impl.c.inc | 132 
 6 files changed, 157 insertions(+), 136 deletions(-)

diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c
index 9df17f93bf..2e3f36a3ef 100644
--- a/target/ppc/excp_helper.c
+++ b/target/ppc/excp_helper.c
@@ -2742,7 +2742,7 @@ void helper_rfmci(CPUPPCState *env)
 }
 #endif /* !CONFIG_USER_ONLY */
 
-void helper_tw(CPUPPCState *env, target_ulong arg1, target_ulong arg2,
+void helper_TW(CPUPPCState *env, target_ulong arg1, target_ulong arg2,
uint32_t flags)
 {
 if (!likely(!(((int32_t)arg1 < (int32_t)arg2 && (flags & 0x10)) ||
@@ -2756,7 +2756,7 @@ void helper_tw(CPUPPCState *env, target_ulong arg1, 
target_ulong arg2,
 }
 
 #ifdef TARGET_PPC64
-void helper_td(CPUPPCState *env, target_ulong arg1, target_ulong arg2,
+void helper_TD(CPUPPCState *env, target_ulong arg1, target_ulong arg2,
uint32_t flags)
 {
 if (!likely(!(((int64_t)arg1 < (int64_t)arg2 && (flags & 0x10)) ||
diff --git a/target/ppc/helper.h b/target/ppc/helper.h
index b5a76f1365..b8af2cf878 100644
--- a/target/ppc/helper.h
+++ b/target/ppc/helper.h
@@ -1,8 +1,8 @@
 DEF_HELPER_FLAGS_3(raise_exception_err, TCG_CALL_NO_WG, noreturn, env, i32, 
i32)
 DEF_HELPER_FLAGS_2(raise_exception, TCG_CALL_NO_WG, noreturn, env, i32)
-DEF_HELPER_FLAGS_4(tw, TCG_CALL_NO_WG, void, env, tl, tl, i32)
+DEF_HELPER_FLAGS_4(TW, TCG_CALL_NO_WG, void, env, tl, tl, i32)
 #if defined(TARGET_PPC64)
-DEF_HELPER_FLAGS_4(td, TCG_CALL_NO_WG, void, env, tl, tl, i32)
+DEF_HELPER_FLAGS_4(TD, TCG_CALL_NO_WG, void, env, tl, tl, i32)
 #endif
 DEF_HELPER_4(HASHST, void, env, tl, tl, tl)
 DEF_HELPER_4(HASHCHK, void, env, tl, tl, tl)
@@ -67,7 +67,7 @@ DEF_HELPER_FLAGS_2(PEXTD, TCG_CALL_NO_RWG_SE, i64, i64, i64)
 DEF_HELPER_FLAGS_1(CDTBCD, TCG_CALL_NO_RWG_SE, tl, tl)
 DEF_HELPER_FLAGS_1(CBCDTD, TCG_CALL_NO_RWG_SE, tl, tl)
 #if defined(TARGET_PPC64)
-DEF_HELPER_FLAGS_2(cmpeqb, TCG_CALL_NO_RWG_SE, i32, tl, tl)
+DEF_HELPER_FLAGS_2(CMPEQB, TCG_CALL_NO_RWG_SE, i32, tl, tl)
 DEF_HELPER_FLAGS_1(popcntw, TCG_CALL_NO_RWG_SE, tl, tl)
 DEF_HELPER_FLAGS_2(bpermd, TCG_CALL_NO_RWG_SE, i64, i64, i64)
 DEF_HELPER_3(srad, tl, env, tl, tl)
diff --git a/target/ppc/insn32.decode b/target/ppc/insn32.decode
index c7cb6e7f37..cb1e4bd307 100644
--- a/target/ppc/insn32.decode
+++ b/target/ppc/insn32.decode
@@ -29,6 +29,9 @@
 _tb   frt frb rc:bool
 @A_tb   .. frt:5 . frb:5 . . rc:1   _tb
 
+_tab_bc   rt ra rb bc
+@A_tab_bc   .. rt:5 ra:5 rb:5 bc:5 . .  _tab_bc
+
   rt ra si:int64_t
 @D  .. rt:5 ra:5 si:s16 
 
@@ -340,6 +343,19 @@ CMP 01 ... - . . . 00 - 
@X_bfl
 CMPL01 ... - . . . 10 - @X_bfl
 CMPI001011 ... - . .    @D_bfs
 CMPLI   001010 ... - . .    @D_bfu
+CMPRB   01 ... - . . . 001100 - @X_bfl
+CMPEQB  01 ... -- . . 001110 -  @X_bf
+
+### Fixed-Point Trap Instructions
+
+TW  01 . . . 000100 -   @X
+TD  01 . . . 0001000100 -   @X
+TWI 11 . .  @D
+TDI 10 . .  @D
+
+### Fixed-Point Select Instruction
+
+ISEL01 . . . . 0 -  @A_tab_bc
 
 ### Fixed-Point Arithmetic Instructions
 
diff --git a/target/ppc/int_helper.c b/target/ppc/int_helper.c
index 585c2b65d3..d12dcc28e1 100644
--- a/target/ppc/int_helper.c
+++ b/target/ppc/int_helper.c
@@ -159,7 +159,7 @@ uint64_t helper_DIVDE(CPUPPCState *env, uint64_t rau, 
uint64_t rbu, uint32_t oe)
 /* When you XOR the pattern and there is a match, that byte will be zero */
 #define hasvalue(x, n)  (haszero((x) ^ pattern(n)))
 
-uint32_t helper_cmpeqb(ta

[PULL 27/72] target/ppc: Remove redundant MEMOP_GET_SIZE macro

2024-05-23 Thread Nicholas Piggin
There is a memop_size() function for this.

Reviewed-by: BALATON Zoltan 
Reviewed-by: Richard Henderson 
Signed-off-by: Nicholas Piggin 
---
 target/ppc/translate.c | 8 +++-
 1 file changed, 3 insertions(+), 5 deletions(-)

diff --git a/target/ppc/translate.c b/target/ppc/translate.c
index 6c103dafe0..cf42dfcc9d 100644
--- a/target/ppc/translate.c
+++ b/target/ppc/translate.c
@@ -2840,8 +2840,6 @@ static void gen_isync(DisasContext *ctx)
 ctx->base.is_jmp = DISAS_EXIT_UPDATE;
 }
 
-#define MEMOP_GET_SIZE(x)  (1 << ((x) & MO_SIZE))
-
 static void gen_load_locked(DisasContext *ctx, MemOp memop)
 {
 TCGv gpr = cpu_gpr[rD(ctx->opcode)];
@@ -2874,7 +2872,7 @@ static void gen_fetch_inc_conditional(DisasContext *ctx, 
MemOp memop,
 TCGv u = tcg_temp_new();
 
 tcg_gen_qemu_ld_tl(t, EA, ctx->mem_idx, memop);
-tcg_gen_addi_tl(t2, EA, MEMOP_GET_SIZE(memop));
+tcg_gen_addi_tl(t2, EA, memop_size(memop));
 tcg_gen_qemu_ld_tl(t2, t2, ctx->mem_idx, memop);
 tcg_gen_addi_tl(u, t, addend);
 
@@ -2884,7 +2882,7 @@ static void gen_fetch_inc_conditional(DisasContext *ctx, 
MemOp memop,
 tcg_gen_qemu_st_tl(u, EA, ctx->mem_idx, memop);
 
 /* RT = (t != t2 ? t : u = 1<<(s*8-1)) */
-tcg_gen_movi_tl(u, 1 << (MEMOP_GET_SIZE(memop) * 8 - 1));
+tcg_gen_movi_tl(u, 1 << (memop_size(memop) * 8 - 1));
 tcg_gen_movcond_tl(cond, cpu_gpr[rD(ctx->opcode)], t, t2, t, u);
 }
 
@@ -3046,7 +3044,7 @@ static void gen_st_atomic(DisasContext *ctx, MemOp memop)
 TCGv ea_plus_s = tcg_temp_new();
 
 tcg_gen_qemu_ld_tl(t, EA, ctx->mem_idx, memop);
-tcg_gen_addi_tl(ea_plus_s, EA, MEMOP_GET_SIZE(memop));
+tcg_gen_addi_tl(ea_plus_s, EA, memop_size(memop));
 tcg_gen_qemu_ld_tl(t2, ea_plus_s, ctx->mem_idx, memop);
 tcg_gen_movcond_tl(TCG_COND_EQ, s, t, t2, src, t);
 tcg_gen_movcond_tl(TCG_COND_EQ, s2, t, t2, src, t2);
-- 
2.43.0




[PULL 26/72] target/ppc: larx/stcx generation need only apply DEF_MEMOP() once

2024-05-23 Thread Nicholas Piggin
Use DEF_MEMOP() consistently in larx and stcx. generation, and apply it
once when it's used rather than where the macros are expanded, to reduce
typing.

Reviewed-by: Richard Henderson 
Signed-off-by: Nicholas Piggin 
---
 target/ppc/translate.c | 18 +-
 1 file changed, 9 insertions(+), 9 deletions(-)

diff --git a/target/ppc/translate.c b/target/ppc/translate.c
index 546f1754de..6c103dafe0 100644
--- a/target/ppc/translate.c
+++ b/target/ppc/translate.c
@@ -2849,7 +2849,7 @@ static void gen_load_locked(DisasContext *ctx, MemOp 
memop)
 
 gen_set_access_type(ctx, ACCESS_RES);
 gen_addr_reg_index(ctx, t0);
-tcg_gen_qemu_ld_tl(gpr, t0, ctx->mem_idx, memop | MO_ALIGN);
+tcg_gen_qemu_ld_tl(gpr, t0, ctx->mem_idx, DEF_MEMOP(memop) | MO_ALIGN);
 tcg_gen_mov_tl(cpu_reserve, t0);
 tcg_gen_movi_tl(cpu_reserve_length, memop_size(memop));
 tcg_gen_mov_tl(cpu_reserve_val, gpr);
@@ -2862,9 +2862,9 @@ static void gen_##name(DisasContext *ctx)  \
 }
 
 /* lwarx */
-LARX(lbarx, DEF_MEMOP(MO_UB))
-LARX(lharx, DEF_MEMOP(MO_UW))
-LARX(lwarx, DEF_MEMOP(MO_UL))
+LARX(lbarx, MO_UB)
+LARX(lharx, MO_UW)
+LARX(lwarx, MO_UL)
 
 static void gen_fetch_inc_conditional(DisasContext *ctx, MemOp memop,
   TCGv EA, TCGCond cond, int addend)
@@ -3109,15 +3109,15 @@ static void gen_##name(DisasContext *ctx)  \
 gen_conditional_store(ctx, memop); \
 }
 
-STCX(stbcx_, DEF_MEMOP(MO_UB))
-STCX(sthcx_, DEF_MEMOP(MO_UW))
-STCX(stwcx_, DEF_MEMOP(MO_UL))
+STCX(stbcx_, MO_UB)
+STCX(sthcx_, MO_UW)
+STCX(stwcx_, MO_UL)
 
 #if defined(TARGET_PPC64)
 /* ldarx */
-LARX(ldarx, DEF_MEMOP(MO_UQ))
+LARX(ldarx, MO_UQ)
 /* stdcx. */
-STCX(stdcx_, DEF_MEMOP(MO_UQ))
+STCX(stdcx_, MO_UQ)
 
 /* lqarx */
 static void gen_lqarx(DisasContext *ctx)
-- 
2.43.0




[PULL 38/72] target/ppc: add SMT support to msgsnd broadcast

2024-05-23 Thread Nicholas Piggin
msgsnd has a broadcast mode that sends hypervisor doorbells to all
threads belonging to the same core as the target. A "subcore" mode
sends to all or one thread depending on 1LPAR mode.

Reviewed-by: Glenn Miles 
Signed-off-by: Nicholas Piggin 
---
 target/ppc/cpu.h  |  6 +-
 target/ppc/excp_helper.c  | 57 +--
 target/ppc/helper.h   |  2 +-
 .../ppc/translate/processor-ctrl-impl.c.inc   |  2 +-
 4 files changed, 46 insertions(+), 21 deletions(-)

diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h
index e4c342b17d..e201b7f6c2 100644
--- a/target/ppc/cpu.h
+++ b/target/ppc/cpu.h
@@ -1163,7 +1163,11 @@ FIELD(FPSCR, FI, FPSCR_FI, 1)
 
 #define DBELL_TYPE_DBELL_SERVER(0x05 << DBELL_TYPE_SHIFT)
 
-#define DBELL_BRDCAST  PPC_BIT(37)
+#define DBELL_BRDCAST_MASK PPC_BITMASK(37, 38)
+#define DBELL_BRDCAST_SHIFT25
+#define DBELL_BRDCAST_SUBPROC  (0x1 << DBELL_BRDCAST_SHIFT)
+#define DBELL_BRDCAST_CORE (0x2 << DBELL_BRDCAST_SHIFT)
+
 #define DBELL_LPIDTAG_SHIFT14
 #define DBELL_LPIDTAG_MASK (0xfff << DBELL_LPIDTAG_SHIFT)
 #define DBELL_PIRTAG_MASK  0x3fff
diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c
index f48eb2eac8..0cd542675f 100644
--- a/target/ppc/excp_helper.c
+++ b/target/ppc/excp_helper.c
@@ -2969,7 +2969,7 @@ void helper_msgsnd(target_ulong rb)
 PowerPCCPU *cpu = POWERPC_CPU(cs);
 CPUPPCState *cenv = >env;
 
-if ((rb & DBELL_BRDCAST) || (cenv->spr[SPR_BOOKE_PIR] == pir)) {
+if ((rb & DBELL_BRDCAST_MASK) || (cenv->spr[SPR_BOOKE_PIR] == pir)) {
 ppc_set_irq(cpu, irq, 1);
 }
 }
@@ -2988,6 +2988,16 @@ static bool dbell_type_server(target_ulong rb)
 return (rb & DBELL_TYPE_MASK) == DBELL_TYPE_DBELL_SERVER;
 }
 
+static inline bool dbell_bcast_core(target_ulong rb)
+{
+return (rb & DBELL_BRDCAST_MASK) == DBELL_BRDCAST_CORE;
+}
+
+static inline bool dbell_bcast_subproc(target_ulong rb)
+{
+return (rb & DBELL_BRDCAST_MASK) == DBELL_BRDCAST_SUBPROC;
+}
+
 void helper_book3s_msgclr(CPUPPCState *env, target_ulong rb)
 {
 if (!dbell_type_server(rb)) {
@@ -2997,32 +3007,43 @@ void helper_book3s_msgclr(CPUPPCState *env, 
target_ulong rb)
 ppc_set_irq(env_archcpu(env), PPC_INTERRUPT_HDOORBELL, 0);
 }
 
-static void book3s_msgsnd_common(int pir, int irq)
+void helper_book3s_msgsnd(CPUPPCState *env, target_ulong rb)
 {
-CPUState *cs;
+int pir = rb & DBELL_PROCIDTAG_MASK;
+bool brdcast = false;
+CPUState *cs, *ccs;
+PowerPCCPU *cpu;
 
-bql_lock();
-CPU_FOREACH(cs) {
-PowerPCCPU *cpu = POWERPC_CPU(cs);
-CPUPPCState *cenv = >env;
+if (!dbell_type_server(rb)) {
+return;
+}
 
-/* TODO: broadcast message to all threads of the same  processor */
-if (cenv->spr_cb[SPR_PIR].default_value == pir) {
-ppc_set_irq(cpu, irq, 1);
-}
+cpu = ppc_get_vcpu_by_pir(pir);
+if (!cpu) {
+return;
 }
-bql_unlock();
-}
+cs = CPU(cpu);
 
-void helper_book3s_msgsnd(target_ulong rb)
-{
-int pir = rb & DBELL_PROCIDTAG_MASK;
+if (dbell_bcast_core(rb) || (dbell_bcast_subproc(rb) &&
+ (env->flags & POWERPC_FLAG_SMT_1LPAR))) {
+brdcast = true;
+}
 
-if (!dbell_type_server(rb)) {
+if (cs->nr_threads == 1 || !brdcast) {
+ppc_set_irq(cpu, PPC_INTERRUPT_HDOORBELL, 1);
 return;
 }
 
-book3s_msgsnd_common(pir, PPC_INTERRUPT_HDOORBELL);
+/*
+ * Why is bql needed for walking CPU list? Answer seems to be because ppc
+ * irq handling needs it, but ppc_set_irq takes the lock itself if needed,
+ * so could this be removed?
+ */
+bql_lock();
+THREAD_SIBLING_FOREACH(cs, ccs) {
+ppc_set_irq(POWERPC_CPU(ccs), PPC_INTERRUPT_HDOORBELL, 1);
+}
+bql_unlock();
 }
 
 #ifdef TARGET_PPC64
diff --git a/target/ppc/helper.h b/target/ppc/helper.h
index 57bf8354e7..dd92c6a937 100644
--- a/target/ppc/helper.h
+++ b/target/ppc/helper.h
@@ -695,7 +695,7 @@ DEF_HELPER_FLAGS_3(store_sr, TCG_CALL_NO_RWG, void, env, 
tl, tl)
 
 DEF_HELPER_1(msgsnd, void, tl)
 DEF_HELPER_2(msgclr, void, env, tl)
-DEF_HELPER_1(book3s_msgsnd, void, tl)
+DEF_HELPER_2(book3s_msgsnd, void, env, tl)
 DEF_HELPER_2(book3s_msgclr, void, env, tl)
 #endif
 
diff --git a/target/ppc/translate/processor-ctrl-impl.c.inc 
b/target/ppc/translate/processor-ctrl-impl.c.inc
index 0142801985..8abbb89630 100644
--- a/target/ppc/translate/processor-ctrl-impl.c.inc
+++ b/target/ppc/translate/processor-ctrl-impl.c.inc
@@ -59,7 +59,7 @@ static bool trans_MSGSND(DisasContext *ctx, arg_X_rb *a)
 
 #if !defined(CONFIG_USER_ONLY)
 if (is_book3s_arch2x(ctx)) {
-gen_helper_book3s_msgsnd(cpu_gpr[a->rb]);
+ 

[PULL 33/72] target/ppc: add helper to write per-LPAR SPRs

2024-05-23 Thread Nicholas Piggin
An SPR can be either per-thread, per-core, or per-LPAR. Per-LPAR means
per-thread or per-core, depending on 1LPAR mode.

Reviewed-by: Glenn Miles 
Signed-off-by: Nicholas Piggin 
---
 target/ppc/spr_common.h |  2 ++
 target/ppc/translate.c  | 28 
 2 files changed, 30 insertions(+)

diff --git a/target/ppc/spr_common.h b/target/ppc/spr_common.h
index 9e40b3b608..85f73b860b 100644
--- a/target/ppc/spr_common.h
+++ b/target/ppc/spr_common.h
@@ -83,6 +83,8 @@ void spr_read_generic(DisasContext *ctx, int gprn, int sprn);
 void spr_write_generic(DisasContext *ctx, int sprn, int gprn);
 void spr_write_generic32(DisasContext *ctx, int sprn, int gprn);
 void spr_core_write_generic(DisasContext *ctx, int sprn, int gprn);
+void spr_core_write_generic32(DisasContext *ctx, int sprn, int gprn);
+void spr_core_lpar_write_generic(DisasContext *ctx, int sprn, int gprn);
 void spr_write_MMCR0(DisasContext *ctx, int sprn, int gprn);
 void spr_write_MMCR1(DisasContext *ctx, int sprn, int gprn);
 void spr_write_MMCRA(DisasContext *ctx, int sprn, int gprn);
diff --git a/target/ppc/translate.c b/target/ppc/translate.c
index fb05047d95..7b525020ef 100644
--- a/target/ppc/translate.c
+++ b/target/ppc/translate.c
@@ -473,6 +473,34 @@ void spr_core_write_generic(DisasContext *ctx, int sprn, 
int gprn)
 spr_store_dump_spr(sprn);
 }
 
+void spr_core_write_generic32(DisasContext *ctx, int sprn, int gprn)
+{
+TCGv t0;
+
+if (!(ctx->flags & POWERPC_FLAG_SMT)) {
+spr_write_generic32(ctx, sprn, gprn);
+return;
+}
+
+if (!gen_serialize(ctx)) {
+return;
+}
+
+t0 = tcg_temp_new();
+tcg_gen_ext32u_tl(t0, cpu_gpr[gprn]);
+gen_helper_spr_core_write_generic(tcg_env, tcg_constant_i32(sprn), t0);
+spr_store_dump_spr(sprn);
+}
+
+void spr_core_lpar_write_generic(DisasContext *ctx, int sprn, int gprn)
+{
+if (ctx->flags & POWERPC_FLAG_SMT_1LPAR) {
+spr_core_write_generic(ctx, sprn, gprn);
+} else {
+spr_write_generic(ctx, sprn, gprn);
+}
+}
+
 static void spr_write_CTRL_ST(DisasContext *ctx, int sprn, int gprn)
 {
 /* This does not implement >1 thread */
-- 
2.43.0




[PULL 69/72] target/ppc/mmu-radix64.c: Drop a local variable

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

The value is only used once so no need to introduce a local variable
for it.

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

diff --git a/target/ppc/mmu-radix64.c b/target/ppc/mmu-radix64.c
index fefa55a5f1..c1e4f00335 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.43.0




[PULL 32/72] target/ppc: Add PPR32 SPR

2024-05-23 Thread Nicholas Piggin
PPR32 provides access to the upper half of PPR.

Reviewed-by: Richard Henderson 
Signed-off-by: Nicholas Piggin 
---
 target/ppc/cpu.h|  1 +
 target/ppc/cpu_init.c   | 12 
 target/ppc/spr_common.h |  2 ++
 target/ppc/translate.c  | 24 
 4 files changed, 39 insertions(+)

diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h
index 2532408be0..141cbefb4c 100644
--- a/target/ppc/cpu.h
+++ b/target/ppc/cpu.h
@@ -2120,6 +2120,7 @@ void ppc_compat_add_property(Object *obj, const char 
*name,
 #define SPR_POWER_MMCRS   (0x37E)
 #define SPR_WORT  (0x37F)
 #define SPR_PPR   (0x380)
+#define SPR_PPR32 (0x382)
 #define SPR_750_GQR0  (0x390)
 #define SPR_440_DNV0  (0x390)
 #define SPR_750_GQR1  (0x391)
diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c
index 927721d49a..6baf7555a7 100644
--- a/target/ppc/cpu_init.c
+++ b/target/ppc/cpu_init.c
@@ -5606,6 +5606,14 @@ static void register_HEIR64_spr(CPUPPCState *env)
  0x);
 }
 
+static void register_power7_common_sprs(CPUPPCState *env)
+{
+spr_register(env, SPR_PPR32, "PPR32",
+ _read_ppr32, _write_ppr32,
+ _read_ppr32, _write_ppr32,
+ 0x);
+}
+
 static void register_power8_tce_address_control_sprs(CPUPPCState *env)
 {
 spr_register_kvm(env, SPR_TAR, "TAR",
@@ -6101,6 +6109,7 @@ static void init_proc_POWER7(CPUPPCState *env)
 register_power6_common_sprs(env);
 register_HEIR32_spr(env);
 register_power6_dbg_sprs(env);
+register_power7_common_sprs(env);
 register_power7_book4_sprs(env);
 
 /* env variables */
@@ -6247,6 +6256,7 @@ static void init_proc_POWER8(CPUPPCState *env)
 register_power6_common_sprs(env);
 register_HEIR32_spr(env);
 register_power6_dbg_sprs(env);
+register_power7_common_sprs(env);
 register_power8_tce_address_control_sprs(env);
 register_power8_ids_sprs(env);
 register_power8_ebb_sprs(env);
@@ -6414,6 +6424,7 @@ static void init_proc_POWER9(CPUPPCState *env)
 register_power6_common_sprs(env);
 register_HEIR32_spr(env);
 register_power6_dbg_sprs(env);
+register_power7_common_sprs(env);
 register_power8_tce_address_control_sprs(env);
 register_power8_ids_sprs(env);
 register_power8_ebb_sprs(env);
@@ -6608,6 +6619,7 @@ static void init_proc_POWER10(CPUPPCState *env)
 register_power6_common_sprs(env);
 register_HEIR64_spr(env);
 register_power6_dbg_sprs(env);
+register_power7_common_sprs(env);
 register_power8_tce_address_control_sprs(env);
 register_power8_ids_sprs(env);
 register_power8_ebb_sprs(env);
diff --git a/target/ppc/spr_common.h b/target/ppc/spr_common.h
index eb2561f593..9e40b3b608 100644
--- a/target/ppc/spr_common.h
+++ b/target/ppc/spr_common.h
@@ -203,6 +203,8 @@ void spr_read_tfmr(DisasContext *ctx, int gprn, int sprn);
 void spr_write_tfmr(DisasContext *ctx, int sprn, int gprn);
 void spr_write_lpcr(DisasContext *ctx, int sprn, int gprn);
 void spr_read_dexcr_ureg(DisasContext *ctx, int gprn, int sprn);
+void spr_read_ppr32(DisasContext *ctx, int sprn, int gprn);
+void spr_write_ppr32(DisasContext *ctx, int sprn, int gprn);
 #endif
 
 void register_low_BATs(CPUPPCState *env);
diff --git a/target/ppc/translate.c b/target/ppc/translate.c
index cf42dfcc9d..fb05047d95 100644
--- a/target/ppc/translate.c
+++ b/target/ppc/translate.c
@@ -1352,6 +1352,30 @@ void spr_read_dexcr_ureg(DisasContext *ctx, int gprn, 
int sprn)
 gen_load_spr(t0, sprn + 16);
 tcg_gen_ext32u_tl(cpu_gpr[gprn], t0);
 }
+
+/* The PPR32 SPR accesses the upper 32-bits of PPR */
+void spr_read_ppr32(DisasContext *ctx, int gprn, int sprn)
+{
+gen_load_spr(cpu_gpr[gprn], SPR_PPR);
+tcg_gen_shri_tl(cpu_gpr[gprn], cpu_gpr[gprn], 32);
+spr_load_dump_spr(SPR_PPR);
+}
+
+void spr_write_ppr32(DisasContext *ctx, int sprn, int gprn)
+{
+TCGv t0 = tcg_temp_new();
+
+/*
+ * Don't clobber the low 32-bits of the PPR. These are all reserved bits
+ * but TCG does implement them, so it would be surprising to zero them
+ * here. "Priority nops" are similarly careful not to clobber reserved
+ * bits.
+ */
+gen_load_spr(t0, SPR_PPR);
+tcg_gen_deposit_tl(t0, t0, cpu_gpr[gprn], 32, 32);
+gen_store_spr(SPR_PPR, t0);
+spr_store_dump_spr(SPR_PPR);
+}
 #endif
 
 #define GEN_HANDLER(name, opc1, opc2, opc3, inval, type)  \
-- 
2.43.0




[PULL 40/72] target/ppc: Remove unused helper

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

The helper_rac function is defined but not used, remove it.

Fixes: 005b69fdcc (target/ppc: Remove PowerPC 601 CPUs)
Reviewed-by: Nicholas Piggin 
Signed-off-by: BALATON Zoltan 
Signed-off-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 dd92c6a937..76b8f25c77 100644
--- a/target/ppc/helper.h
+++ b/target/ppc/helper.h
@@ -701,8 +701,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 d9d950e220..d4388e66be 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.43.0




[PULL 71/72] target/ppc: Move out BookE and related MMU functions from mmu_common.c

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

Add a new mmu-booke.c file for BookE and related MMU bits from
mmu_common.c.

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

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

[PULL 72/72] target/ppc: Remove pp_check() and reuse ppc_hash32_pp_prot()

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

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

Reviewed-by: Nicholas Piggin 
Signed-off-by: BALATON Zoltan 
[np: move ppc_hash32_pp_prot inline without changing it]
Signed-off-by: Nicholas Piggin 
---
 target/ppc/mmu-hash32.c | 45 -
 target/ppc/mmu-hash32.h | 45 +
 target/ppc/mmu_common.c | 44 ++--
 3 files changed, 47 insertions(+), 87 deletions(-)

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

[PULL 35/72] target/ppc: Add SMT support to PTCR SPR

2024-05-23 Thread Nicholas Piggin
PTCR is a per-core register.

Reviewed-by: Glenn Miles 
Signed-off-by: Nicholas Piggin 
---
 target/ppc/misc_helper.c | 16 ++--
 target/ppc/translate.c   |  4 
 2 files changed, 18 insertions(+), 2 deletions(-)

diff --git a/target/ppc/misc_helper.c b/target/ppc/misc_helper.c
index 6f419c9346..a67930d031 100644
--- a/target/ppc/misc_helper.c
+++ b/target/ppc/misc_helper.c
@@ -173,6 +173,7 @@ void helper_store_sdr1(CPUPPCState *env, target_ulong val)
 void helper_store_ptcr(CPUPPCState *env, target_ulong val)
 {
 if (env->spr[SPR_PTCR] != val) {
+CPUState *cs = env_cpu(env);
 PowerPCCPU *cpu = env_archcpu(env);
 target_ulong ptcr_mask = PTCR_PATB | PTCR_PATS;
 target_ulong patbsize = val & PTCR_PATS;
@@ -194,8 +195,19 @@ void helper_store_ptcr(CPUPPCState *env, target_ulong val)
 return;
 }
 
-env->spr[SPR_PTCR] = val;
-tlb_flush(env_cpu(env));
+if (cs->nr_threads == 1 || !(env->flags & POWERPC_FLAG_SMT_1LPAR)) {
+env->spr[SPR_PTCR] = val;
+tlb_flush(cs);
+} else {
+CPUState *ccs;
+
+THREAD_SIBLING_FOREACH(cs, ccs) {
+PowerPCCPU *ccpu = POWERPC_CPU(ccs);
+CPUPPCState *cenv = >env;
+cenv->spr[SPR_PTCR] = val;
+tlb_flush(ccs);
+}
+}
 }
 }
 
diff --git a/target/ppc/translate.c b/target/ppc/translate.c
index 7b525020ef..64131bf15c 100644
--- a/target/ppc/translate.c
+++ b/target/ppc/translate.c
@@ -909,6 +909,10 @@ void spr_write_hior(DisasContext *ctx, int sprn, int gprn)
 }
 void spr_write_ptcr(DisasContext *ctx, int sprn, int gprn)
 {
+if (!gen_serialize_core(ctx)) {
+return;
+}
+
 gen_helper_store_ptcr(tcg_env, cpu_gpr[gprn]);
 }
 
-- 
2.43.0




[PULL 58/72] target/ppc/mmu_common.c: Remove BookE from direct store handling

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

As BookE never returns -4 we can drop BookE from the direct store case
in ppc_jumbo_xlate().

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

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




[PULL 50/72] target/ppc/mmu_common.c: Split off real mode cases in get_physical_address_wtlb()

2024-05-23 Thread Nicholas Piggin
From: 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.

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

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




[PULL 57/72] target/ppc/mmu_common.c: Don't use mmu_ctx_t in mmubooke206_get_physical_address()

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

mmubooke206_get_physical_address() only uses the raddr and prot fields
from mmu_ctx_t. Pass these directly instead of using a ctx struct.

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

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




[PULL 59/72] target/ppc/mmu_common.c: Split off BookE handling from ppc_jumbo_xlate()

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

Introduce ppc_booke_xlate() to handle BookE and BookE 2.06 cases to
reduce ppc_jumbo_xlate() further.

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

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

[PULL 64/72] target/ppc/mmu_common.c: Transform ppc_jumbo_xlate() into ppc_6xx_xlate()

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

Now that only 6xx cases left in ppc_jumbo_xlate() we can change it
to ppc_6xx_xlate() also removing get_physical_address_wtlb().

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

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




[PULL 63/72] target/ppc/mmu_common.c: Split off 40x cases from ppc_jumbo_xlate()

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

Introduce ppc_40x_xlate() to split off 40x handlning leaving only 6xx
in ppc_jumbo_xlate() now.

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

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

[PULL 19/72] target/ppc: Move VMX storage access instructions to decodetree

2024-05-23 Thread Nicholas Piggin
From: Chinmay Rath 

Moving the following instructions to decodetree specification :

{l,st}ve{b,h,w}x,
{l,st}v{x,xl},
lvs{l,r}: X-form

The changes were verified by validating that the tcg ops generated by those
instructions remain the same, which were captured using the '-d in_asm,op' flag.

Reviewed-by: Richard Henderson 
Signed-off-by: Chinmay Rath 
Signed-off-by: Nicholas Piggin 
---
 target/ppc/helper.h |  12 +-
 target/ppc/insn32.decode|  17 +++
 target/ppc/mem_helper.c |  12 +-
 target/ppc/translate.c  |   2 -
 target/ppc/translate/vmx-impl.c.inc | 221 
 target/ppc/translate/vmx-ops.c.inc  |  19 ---
 6 files changed, 120 insertions(+), 163 deletions(-)

diff --git a/target/ppc/helper.h b/target/ppc/helper.h
index 4267917615..6d6f31366c 100644
--- a/target/ppc/helper.h
+++ b/target/ppc/helper.h
@@ -267,12 +267,12 @@ DEF_HELPER_5(VMSUMSHS, void, env, avr, avr, avr, avr)
 DEF_HELPER_FLAGS_5(VMLADDUHM, TCG_CALL_NO_RWG, void, avr, avr, avr, avr, i32)
 DEF_HELPER_FLAGS_2(mtvscr, TCG_CALL_NO_RWG, void, env, i32)
 DEF_HELPER_FLAGS_1(mfvscr, TCG_CALL_NO_RWG, i32, env)
-DEF_HELPER_3(lvebx, void, env, avr, tl)
-DEF_HELPER_3(lvehx, void, env, avr, tl)
-DEF_HELPER_3(lvewx, void, env, avr, tl)
-DEF_HELPER_3(stvebx, void, env, avr, tl)
-DEF_HELPER_3(stvehx, void, env, avr, tl)
-DEF_HELPER_3(stvewx, void, env, avr, tl)
+DEF_HELPER_3(LVEBX, void, env, avr, tl)
+DEF_HELPER_3(LVEHX, void, env, avr, tl)
+DEF_HELPER_3(LVEWX, void, env, avr, tl)
+DEF_HELPER_3(STVEBX, void, env, avr, tl)
+DEF_HELPER_3(STVEHX, void, env, avr, tl)
+DEF_HELPER_3(STVEWX, void, env, avr, tl)
 #if defined(TARGET_PPC64)
 DEF_HELPER_4(lxvl, void, env, tl, vsr, tl)
 DEF_HELPER_4(lxvll, void, env, tl, vsr, tl)
diff --git a/target/ppc/insn32.decode b/target/ppc/insn32.decode
index dc62bc90aa..11be21d230 100644
--- a/target/ppc/insn32.decode
+++ b/target/ppc/insn32.decode
@@ -661,6 +661,23 @@ DSCRIQ  11 . . .. 001100010 .   
@Z22_tap_sh_rc
 
 VPMSUMD 000100 . . . 10011001000@VX
 
+## Vector Load/Store Instructions
+
+LVEBX   01 . . . 000111 -   @X
+LVEHX   01 . . . 100111 -   @X
+LVEWX   01 . . . 0001000111 -   @X
+LVX 01 . . . 0001100111 -   @X
+LVXL01 . . . 0101100111 -   @X
+
+STVEBX  01 . . . 001111 -   @X
+STVEHX  01 . . . 0010100111 -   @X
+STVEWX  01 . . . 0011000111 -   @X
+STVX01 . . . 0011100111 -   @X
+STVXL   01 . . . 000111 -   @X
+
+LVSL01 . . . 000110 -   @X
+LVSR01 . . . 100110 -   @X
+
 ## Vector Integer Instructions
 
 VCMPEQUB000100 . . . . 000110   @VC
diff --git a/target/ppc/mem_helper.c b/target/ppc/mem_helper.c
index ea7e8443a8..f88155ad45 100644
--- a/target/ppc/mem_helper.c
+++ b/target/ppc/mem_helper.c
@@ -404,9 +404,9 @@ target_ulong helper_lscbx(CPUPPCState *env, target_ulong 
addr, uint32_t reg,
 }   \
 }
 #define I(x) (x)
-LVE(lvebx, cpu_ldub_data_ra, I, u8)
-LVE(lvehx, cpu_lduw_data_ra, bswap16, u16)
-LVE(lvewx, cpu_ldl_data_ra, bswap32, u32)
+LVE(LVEBX, cpu_ldub_data_ra, I, u8)
+LVE(LVEHX, cpu_lduw_data_ra, bswap16, u16)
+LVE(LVEWX, cpu_ldl_data_ra, bswap32, u32)
 #undef I
 #undef LVE
 
@@ -432,9 +432,9 @@ LVE(lvewx, cpu_ldl_data_ra, bswap32, u32)
 }   \
 }
 #define I(x) (x)
-STVE(stvebx, cpu_stb_data_ra, I, u8)
-STVE(stvehx, cpu_stw_data_ra, bswap16, u16)
-STVE(stvewx, cpu_stl_data_ra, bswap32, u32)
+STVE(STVEBX, cpu_stb_data_ra, I, u8)
+STVE(STVEHX, cpu_stw_data_ra, bswap16, u16)
+STVE(STVEWX, cpu_stl_data_ra, bswap32, u32)
 #undef I
 #undef LVE
 
diff --git a/target/ppc/translate.c b/target/ppc/translate.c
index 2cfa7d37ee..2c39605273 100644
--- a/target/ppc/translate.c
+++ b/target/ppc/translate.c
@@ -5790,8 +5790,6 @@ GEN_HANDLER2_E(icbt_440, "icbt", 0x1F, 0x16, 0x00, 
0x03E1,
PPC_BOOKE, PPC2_BOOKE206),
 GEN_HANDLER2(icbt_440, "icbt", 0x1F, 0x06, 0x08, 0x03E1,
  PPC_440_SPEC),
-GEN_HANDLER(lvsl, 0x1f, 0x06, 0x00, 0x0001, PPC_ALTIVEC),
-GEN_HANDLER(lvsr, 0x1f, 0x06, 0x01, 0x0001, PPC_ALTIVEC),
 GEN_HANDLER(mfvscr, 0x04, 0x2, 0x18, 0x001ff800, PPC_ALTIVEC),
 GEN_HANDLER(mtvscr, 0x04, 0x2, 0x19, 0x03ff, PPC_ALTIVEC),
 
diff --git a/target/ppc/translate/vmx-impl.c.inc 
b/target/ppc/translate/vmx-impl.c.inc
index b56e615c24..4d5e743cfe 100644
--- a/target/ppc/translate/vmx-impl.c.inc
+++ b/target/ppc/translate/vmx-impl.c.inc
@@ -14,125 +14,88 @@ static inline TCGv_ptr gen_avr_ptr(int reg)
 ret

[PULL 44/72] target/ppc/mmu_common.c: Drop cases for unimplemented MPC8xx MMU

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

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

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

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




[PULL 41/72] target/ppc/mmu_common.c: Move calculation of a value closer to its usage

2024-05-23 Thread Nicholas Piggin
From: 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.

Reviewed-by: Nicholas Piggin 
Signed-off-by: BALATON Zoltan 
Signed-off-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.43.0




[PULL 43/72] target/ppc/mmu_common.c: Simplify checking for real mode

2024-05-23 Thread Nicholas Piggin
From: 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.

Reviewed-by: Nicholas Piggin 
Signed-off-by: BALATON Zoltan 
Signed-off-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.43.0




[PULL 61/72] target/ppc/mmu_common.c: Simplify ppc_booke_xlate() part 2

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

Merge the code fetch and data access cases in a common switch.

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

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




[PULL 36/72] target/ppc: Implement LDBAR, TTR SPRs

2024-05-23 Thread Nicholas Piggin
LDBAR, TTR are a Power-specific SPRs. These simple implementations
are enough for IBM proprietary firmware for now.

Reviewed-by: Glenn Miles 
Signed-off-by: Nicholas Piggin 
---
 target/ppc/cpu.h  |  2 ++
 target/ppc/cpu_init.c | 10 ++
 2 files changed, 12 insertions(+)

diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h
index 141cbefb4c..823be85d03 100644
--- a/target/ppc/cpu.h
+++ b/target/ppc/cpu.h
@@ -2098,6 +2098,7 @@ void ppc_compat_add_property(Object *obj, const char 
*name,
 #define SPR_DEXCR (0x33C)
 #define SPR_IC(0x350)
 #define SPR_VTB   (0x351)
+#define SPR_LDBAR (0x352)
 #define SPR_MMCRC (0x353)
 #define SPR_PSSCR (0x357)
 #define SPR_440_INV0  (0x370)
@@ -2144,6 +2145,7 @@ void ppc_compat_add_property(Object *obj, const char 
*name,
 #define SPR_440_IVLIM (0x399)
 #define SPR_TSCR  (0x399)
 #define SPR_750_DMAU  (0x39A)
+#define SPR_POWER_TTR (0x39A)
 #define SPR_750_DMAL  (0x39B)
 #define SPR_440_RSTCFG(0x39B)
 #define SPR_BOOKE_DCDBTRL (0x39C)
diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c
index 415cc7a4e2..d181adc5f1 100644
--- a/target/ppc/cpu_init.c
+++ b/target/ppc/cpu_init.c
@@ -5767,6 +5767,16 @@ static void register_power_common_book4_sprs(CPUPPCState 
*env)
  _access_nop, _write_generic,
  _access_nop, _write_generic,
  0x);
+spr_register_hv(env, SPR_LDBAR, "LDBAR",
+ SPR_NOACCESS, SPR_NOACCESS,
+ SPR_NOACCESS, SPR_NOACCESS,
+ _read_generic, _core_lpar_write_generic,
+ 0x);
+spr_register_hv(env, SPR_POWER_TTR, "TTR",
+ SPR_NOACCESS, SPR_NOACCESS,
+ SPR_NOACCESS, SPR_NOACCESS,
+ _read_generic, _core_write_generic,
+ 0x);
 #endif
 }
 
-- 
2.43.0




[PULL 47/72] target/ppc/mmu_common.c: Move some debug logging

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

Move the debug logging within ppc6xx_tlb_check() from after its only
call to simplify the caller.

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

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




[PULL 54/72] target/ppc/mmu_common.c: Replace hard coded constants in ppc_jumbo_xlate()

2024-05-23 Thread Nicholas Piggin
From: 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.

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

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




[PULL 06/72] target/ppc: Move sync instructions to decodetree

2024-05-23 Thread Nicholas Piggin
This tries to faithfully reproduce the odd BookE logic. Note the
e206 check in gen_msync_4xx() is always false, so not carried over.

It does change the handling of non-zero reserved bits outside the
defined fields from being illegal to being ignored, which the
architecture specifies ot help with backward compatibility of new
fields. The existing behaviour causes illegal instruction exceptions
when using new POWER10 sync variants that add new fields, after this
the instructions are accepted and are implemented as supersets of
the new behaviour, as intended.

Reviewed-by: Chinmay Rath 
Signed-off-by: Nicholas Piggin 
---
 target/ppc/insn32.decode |   7 ++
 target/ppc/translate.c   | 102 +
 target/ppc/translate/misc-impl.c.inc | 130 +++
 3 files changed, 139 insertions(+), 100 deletions(-)
 create mode 100644 target/ppc/translate/misc-impl.c.inc

diff --git a/target/ppc/insn32.decode b/target/ppc/insn32.decode
index eada59f59f..6b89804b15 100644
--- a/target/ppc/insn32.decode
+++ b/target/ppc/insn32.decode
@@ -998,3 +998,10 @@ MSGSND  01 - - . 0011001110 -   
@X_rb
 MSGCLRP 01 - - . 0010101110 -   @X_rb
 MSGSNDP 01 - - . 0010001110 -   @X_rb
 MSGSYNC 01 - - - 1101110110 -
+
+# Memory Barrier Instructions
+
+_sync l
+@X_sync .. ... l:2 . . .. .   _sync
+SYNC01 --- ..  - - 1001010110 -   @X_sync
+EIEIO   01 - - - 1101010110 -
diff --git a/target/ppc/translate.c b/target/ppc/translate.c
index 24461c2d1b..a70c5ed951 100644
--- a/target/ppc/translate.c
+++ b/target/ppc/translate.c
@@ -3422,59 +3422,6 @@ static void gen_stswx(DisasContext *ctx)
 gen_helper_stsw(tcg_env, t0, t1, t2);
 }
 
-/***Memory synchronisation ***/
-/* eieio */
-static void gen_eieio(DisasContext *ctx)
-{
-TCGBar bar = TCG_MO_ALL;
-
-/*
- * eieio has complex semanitcs. It provides memory ordering between
- * operations in the set:
- * - loads from CI memory.
- * - stores to CI memory.
- * - stores to WT memory.
- *
- * It separately also orders memory for operations in the set:
- * - stores to cacheble memory.
- *
- * It also serializes instructions:
- * - dcbt and dcbst.
- *
- * It separately serializes:
- * - tlbie and tlbsync.
- *
- * And separately serializes:
- * - slbieg, slbiag, and slbsync.
- *
- * The end result is that CI memory ordering requires TCG_MO_ALL
- * and it is not possible to special-case more relaxed ordering for
- * cacheable accesses. TCG_BAR_SC is required to provide this
- * serialization.
- */
-
-/*
- * POWER9 has a eieio instruction variant using bit 6 as a hint to
- * tell the CPU it is a store-forwarding barrier.
- */
-if (ctx->opcode & 0x200) {
-/*
- * ISA says that "Reserved fields in instructions are ignored
- * by the processor". So ignore the bit 6 on non-POWER9 CPU but
- * as this is not an instruction software should be using,
- * complain to the user.
- */
-if (!(ctx->insns_flags2 & PPC2_ISA300)) {
-qemu_log_mask(LOG_GUEST_ERROR, "invalid eieio using bit 6 at @"
-  TARGET_FMT_lx "\n", ctx->cia);
-} else {
-bar = TCG_MO_ST_LD;
-}
-}
-
-tcg_gen_mb(bar | TCG_BAR_SC);
-}
-
 #if !defined(CONFIG_USER_ONLY)
 static inline void gen_check_tlb_flush(DisasContext *ctx, bool global)
 {
@@ -3883,31 +3830,6 @@ static void gen_stqcx_(DisasContext *ctx)
 }
 #endif /* defined(TARGET_PPC64) */
 
-/* sync */
-static void gen_sync(DisasContext *ctx)
-{
-TCGBar bar = TCG_MO_ALL;
-uint32_t l = (ctx->opcode >> 21) & 3;
-
-if ((l == 1) && (ctx->insns_flags2 & PPC2_MEM_LWSYNC)) {
-bar = TCG_MO_LD_LD | TCG_MO_LD_ST | TCG_MO_ST_ST;
-}
-
-/*
- * We may need to check for a pending TLB flush.
- *
- * We do this on ptesync (l == 2) on ppc64 and any sync pn ppc32.
- *
- * Additionally, this can only happen in kernel mode however so
- * check MSR_PR as well.
- */
-if (((l == 2) || !(ctx->insns_flags & PPC_64B)) && !ctx->pr) {
-gen_check_tlb_flush(ctx, true);
-}
-
-tcg_gen_mb(bar | TCG_BAR_SC);
-}
-
 /* wait */
 static void gen_wait(DisasContext *ctx)
 {
@@ -6016,23 +5938,6 @@ static void gen_dlmzb(DisasContext *ctx)
  cpu_gpr[rS(ctx->opcode)], cpu_gpr[rB(ctx->opcode)], t0);
 }
 
-/* mbar replaces eieio on 440 */
-static void gen_mbar(DisasContext *ctx)
-{
-/* interpreted as no-op */
-}
-
-/* msync replaces sync on 440 */
-static void gen_msync_4xx(DisasContext *ctx)
-{
-

[PULL 53/72] target/ppc/mmu_common.c: Deindent ppc_jumbo_xlate()

2024-05-23 Thread Nicholas Piggin
From: 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.

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

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

[PULL 15/72] target/ppc: Move multiply fixed-point insns (64-bit operands) to decodetree.

2024-05-23 Thread Nicholas Piggin
From: Chinmay Rath 

Moving the following instructions to decodetree :

mul{ld, ldo, hd, hdu}[.]: XO-form
madd{hd, hdu, ld}   : VA-form

The changes were verified by validating that the tcg ops generated by those
instructions remain the same, which were captured with the '-d in_asm,op'
flag.

Reviewed-by: Richard Henderson 
Signed-off-by: Chinmay Rath 
[np: 32-bit compile fix]
Signed-off-by: Nicholas Piggin 
---
 target/ppc/insn32.decode   |   9 ++
 target/ppc/translate.c | 101 
 target/ppc/translate/fixedpoint-impl.c.inc | 105 +
 3 files changed, 114 insertions(+), 101 deletions(-)

diff --git a/target/ppc/insn32.decode b/target/ppc/insn32.decode
index 3051792a56..46199488f7 100644
--- a/target/ppc/insn32.decode
+++ b/target/ppc/insn32.decode
@@ -384,6 +384,15 @@ MODUW   01 . . . 011011 -   @X
 DARN01 . --- .. - 100011 -  @X_tl
 NEG 01 . . - . 001101000 .  @XO_ta
 
+MULLD   01 . . . 0 011101001 .  @XO_tab_rc
+MULLDO  01 . . . 1 011101001 .  @XO_tab_rc
+MULHD   01 . . . - 001001001 .  @XO_tab_rc
+MULHDU  01 . . . - 01001 .  @XO_tab_rc
+
+MADDLD  000100 . . . . 110011   @VA
+MADDHD  000100 . . . . 11   @VA
+MADDHDU 000100 . . . . 110001   @VA
+
 ## Fixed-Point Logical Instructions
 
 CFUGED  01 . . . 0011011100 -   @X
diff --git a/target/ppc/translate.c b/target/ppc/translate.c
index 3756b0c495..c76c4c9054 100644
--- a/target/ppc/translate.c
+++ b/target/ppc/translate.c
@@ -1917,62 +1917,6 @@ GEN_INT_ARITH_MODD(modud, 0x08, 0);
 GEN_INT_ARITH_MODD(modsd, 0x18, 1);
 #endif
 
-#if defined(TARGET_PPC64)
-/* mulhd  mulhd. */
-static void gen_mulhd(DisasContext *ctx)
-{
-TCGv lo = tcg_temp_new();
-tcg_gen_muls2_tl(lo, cpu_gpr[rD(ctx->opcode)],
- cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
-if (unlikely(Rc(ctx->opcode) != 0)) {
-gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
-}
-}
-
-/* mulhdu  mulhdu. */
-static void gen_mulhdu(DisasContext *ctx)
-{
-TCGv lo = tcg_temp_new();
-tcg_gen_mulu2_tl(lo, cpu_gpr[rD(ctx->opcode)],
- cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
-if (unlikely(Rc(ctx->opcode) != 0)) {
-gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
-}
-}
-
-/* mulld  mulld. */
-static void gen_mulld(DisasContext *ctx)
-{
-tcg_gen_mul_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)],
-   cpu_gpr[rB(ctx->opcode)]);
-if (unlikely(Rc(ctx->opcode) != 0)) {
-gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
-}
-}
-
-/* mulldo  mulldo. */
-static void gen_mulldo(DisasContext *ctx)
-{
-TCGv_i64 t0 = tcg_temp_new_i64();
-TCGv_i64 t1 = tcg_temp_new_i64();
-
-tcg_gen_muls2_i64(t0, t1, cpu_gpr[rA(ctx->opcode)],
-  cpu_gpr[rB(ctx->opcode)]);
-tcg_gen_mov_i64(cpu_gpr[rD(ctx->opcode)], t0);
-
-tcg_gen_sari_i64(t0, t0, 63);
-tcg_gen_setcond_i64(TCG_COND_NE, cpu_ov, t0, t1);
-if (is_isa300(ctx)) {
-tcg_gen_mov_tl(cpu_ov32, cpu_ov);
-}
-tcg_gen_or_tl(cpu_so, cpu_so, cpu_ov);
-
-if (unlikely(Rc(ctx->opcode) != 0)) {
-gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
-}
-}
-#endif
-
 /* Common subf function */
 static inline void gen_op_arith_subf(DisasContext *ctx, TCGv ret, TCGv arg1,
  TCGv arg2, bool add_ca, bool compute_ca,
@@ -5795,36 +5739,6 @@ static void gen_icbt_440(DisasContext *ctx)
  */
 }
 
-#if defined(TARGET_PPC64)
-static void gen_maddld(DisasContext *ctx)
-{
-TCGv_i64 t1 = tcg_temp_new_i64();
-
-tcg_gen_mul_i64(t1, cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
-tcg_gen_add_i64(cpu_gpr[rD(ctx->opcode)], t1, cpu_gpr[rC(ctx->opcode)]);
-}
-
-/* maddhd maddhdu */
-static void gen_maddhd_maddhdu(DisasContext *ctx)
-{
-TCGv_i64 lo = tcg_temp_new_i64();
-TCGv_i64 hi = tcg_temp_new_i64();
-TCGv_i64 t1 = tcg_temp_new_i64();
-
-if (Rc(ctx->opcode)) {
-tcg_gen_mulu2_i64(lo, hi, cpu_gpr[rA(ctx->opcode)],
-  cpu_gpr[rB(ctx->opcode)]);
-tcg_gen_movi_i64(t1, 0);
-} else {
-tcg_gen_muls2_i64(lo, hi, cpu_gpr[rA(ctx->opcode)],
-  cpu_gpr[rB(ctx->opcode)]);
-tcg_gen_sari_i64(t1, cpu_gpr[rC(ctx->opcode)], 63);
-}
-tcg_gen_add2_i64(t1, cpu_gpr[rD(ctx->opcode)], lo, hi,
- cpu_gpr[rC(ctx->opcode)], t1);
-}
-#endif /* defined(TARGET_PPC64) */
-
 static void gen_tbegin(DisasContext *ctx)
 {
 if (unlikely(!ctx->tm_enabled)) {
@@ -6190,9 +6104,6 @@ GEN

  1   2   3   4   5   6   7   8   9   10   >