target/ppc: Add LPAR-per-core vs per-thread mode flag

The Power ISA has the concept of sub-processors:

  Hardware is allowed to sub-divide a multi-threaded processor into
  "sub-processors" that appear to privileged programs as multi-threaded
  processors with fewer threads.

POWER9 and POWER10 have two modes, either every thread is a
sub-processor or all threads appear as one multi-threaded processor. In
the user manuals these are known as "LPAR per thread" / "Thread LPAR",
and "LPAR per core" / "1 LPAR", respectively.

The practical difference is: in thread LPAR mode, non-hypervisor SPRs
are not shared between threads and msgsndp can not be used to message
siblings. In 1 LPAR mode, some SPRs are shared and msgsndp is usable.
Thrad LPAR allows multiple partitions to run concurrently on the same
core, and is a requirement for KVM to run on POWER9/10 (which does not
gang-schedule an LPAR on all threads of a core like POWER8 KVM).

Traditionally, SMT in PAPR environments including PowerVM and the
pseries QEMU machine with KVM acceleration behaves as in 1 LPAR mode.
In OPAL systems, Thread LPAR is used. When adding SMT to the powernv
machine, it is therefore preferable to emulate Thread LPAR.

To account for this difference between pseries and powernv, an LPAR mode
flag is added such that SPRs can be implemented as per-LPAR shared, and
that becomes either per-thread or per-core depending on the flag.

Reviewed-by: Joel Stanley <joel@jms.id.au>
Reviewed-by: Cédric Le Goater <clg@kaod.org>
Tested-by: Cédric Le Goater <clg@kaod.org>
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
Message-ID: <20230705120631.27670-2-npiggin@gmail.com>
Signed-off-by: Daniel Henrique Barboza <danielhb413@gmail.com>
This commit is contained in:
Nicholas Piggin 2023-07-05 22:06:28 +10:00 committed by Daniel Henrique Barboza
parent ed75a12357
commit 3401ea3cfe
6 changed files with 35 additions and 5 deletions

View file

@ -246,9 +246,9 @@ static inline bool gen_serialize(DisasContext *ctx)
}
#if defined(TARGET_PPC64) && !defined(CONFIG_USER_ONLY)
static inline bool gen_serialize_core(DisasContext *ctx)
static inline bool gen_serialize_core_lpar(DisasContext *ctx)
{
if (ctx->flags & POWERPC_FLAG_SMT) {
if (ctx->flags & POWERPC_FLAG_SMT_1LPAR) {
return gen_serialize(ctx);
}
@ -451,7 +451,8 @@ static void spr_write_CTRL_ST(DisasContext *ctx, int sprn, int gprn)
void spr_write_CTRL(DisasContext *ctx, int sprn, int gprn)
{
if (!(ctx->flags & POWERPC_FLAG_SMT)) {
if (!(ctx->flags & POWERPC_FLAG_SMT_1LPAR)) {
/* CTRL behaves as 1-thread in LPAR-per-thread mode */
spr_write_CTRL_ST(ctx, sprn, gprn);
goto out;
}
@ -815,7 +816,7 @@ void spr_write_pcr(DisasContext *ctx, int sprn, int gprn)
/* DPDES */
void spr_read_dpdes(DisasContext *ctx, int gprn, int sprn)
{
if (!gen_serialize_core(ctx)) {
if (!gen_serialize_core_lpar(ctx)) {
return;
}
@ -824,7 +825,7 @@ void spr_read_dpdes(DisasContext *ctx, int gprn, int sprn)
void spr_write_dpdes(DisasContext *ctx, int sprn, int gprn)
{
if (!gen_serialize_core(ctx)) {
if (!gen_serialize_core_lpar(ctx)) {
return;
}