Re: [PATCH v2 4/4] vga/cirrus: deprecate, don't build by default

2024-05-30 Thread BALATON Zoltan

On Thu, 30 May 2024, Gerd Hoffmann wrote:

stdvga is the much better option.

Signed-off-by: Gerd Hoffmann 
---
hw/display/cirrus_vga.c | 1 +
hw/display/cirrus_vga_isa.c | 1 +
hw/display/Kconfig  | 1 -
3 files changed, 2 insertions(+), 1 deletion(-)

diff --git a/hw/display/cirrus_vga.c b/hw/display/cirrus_vga.c
index 150883a97166..81421be1f89d 100644
--- a/hw/display/cirrus_vga.c
+++ b/hw/display/cirrus_vga.c
@@ -3007,6 +3007,7 @@ static void cirrus_vga_class_init(ObjectClass *klass, 
void *data)
dc->vmsd = _pci_cirrus_vga;
device_class_set_props(dc, pci_vga_cirrus_properties);
dc->hotpluggable = false;
+klass->deprecation_note = "use stdvga instead";
}

static const TypeInfo cirrus_vga_info = {
diff --git a/hw/display/cirrus_vga_isa.c b/hw/display/cirrus_vga_isa.c
index 84be51670ed8..3abbf490 100644
--- a/hw/display/cirrus_vga_isa.c
+++ b/hw/display/cirrus_vga_isa.c
@@ -85,6 +85,7 @@ static void isa_cirrus_vga_class_init(ObjectClass *klass, 
void *data)
dc->realize = isa_cirrus_vga_realizefn;
device_class_set_props(dc, isa_cirrus_vga_properties);
set_bit(DEVICE_CATEGORY_DISPLAY, dc->categories);
+klass->deprecation_note = "use stdvga instead";


Excepr some old OSes work better with this than stdvga so could this be 
left and not removed? Does it cause a lot of work to keep this device? I 
thought it's stable already and were not many changes for it lately. If 
something works why drop it?


Regards,
BALATON Zoltan


}

static const TypeInfo isa_cirrus_vga_info = {
diff --git a/hw/display/Kconfig b/hw/display/Kconfig
index a4552c8ed78d..cd0779396890 100644
--- a/hw/display/Kconfig
+++ b/hw/display/Kconfig
@@ -11,7 +11,6 @@ config FW_CFG_DMA

config VGA_CIRRUS
bool
-default y if PCI_DEVICES
depends on PCI
select VGA






Re: TCG change broke MorphOS boot on sam460ex

2024-05-27 Thread BALATON Zoltan

On Tue, 28 May 2024, 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. We would either need to make sure the TB 
runs until the sync or somehow emulate the shadow TLB. I've experimented with 
the latter but I could not make it work (and unexpectedly keeping a cache of 
the most recently used entries is slower than always searching through all 
TLB entries as done now so I've abandoned that idea). The problem is that an 
entry is modified by multiple tlbwe instructions but these can come in any 
order (and sometimes only one of them is done like invalidating an entry 
seems to only do one write) so I don't know when to copy the new entry to the 
TLB and when to wait for more parts and keep the old one. Any idea how to fix 
this?


Also I'm not sure if it's related but by running the stream benchmark on 
sam460ex now I can reproduce some memory access problem but I'm not sure what 
causes it. The full output of that benchmark under AmigaOS on sam460ex is 
this:


-
STREAM version $Revision: 5.10 $
-
This system uses 8 bytes per array element.
-
Array size = 1000 (elements), Offset = 0 (elements)
Memory per array = 76.3 MiB (= 0.1 GiB).
Total memory 

Re: TCG change broke MorphOS boot on sam460ex

2024-05-27 Thread BALATON Zoltan

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. We would either need to make 
sure the TB runs until the sync or somehow emulate the shadow TLB. I've 
experimented with the latter but I could not make it work (and 
unexpectedly keeping a cache of the most recently used entries is slower 
than always searching through all TLB entries as done now so I've 
abandoned that idea). The problem is that an entry is modified by multiple 
tlbwe instructions but these can come in any order (and sometimes only one 
of them is done like invalidating an entry seems to only do one write) so 
I don't know when to copy the new entry to the TLB and when to wait for 
more parts and keep the old one. Any idea how to fix this?


Also I'm not sure if it's related but by running the stream benchmark on 
sam460ex now I can reproduce some memory access problem but I'm not sure 
what causes it. The full output of that benchmark under AmigaOS on 
sam460ex is this:


-
STREAM version $Revision: 5.10 $
-
This system uses 8 bytes per array element.
-
Array size = 1000 (elements), Offset = 0 (elements)
Memory per array = 76.3 MiB (= 0.1 GiB).
Total memory required = 228.9 MiB (= 0.2 GiB).
Each kernel will 

Re: [PATCH 00/43] Remaining MMU clean up patches

2024-05-27 Thread BALATON Zoltan

On Mon, 27 May 2024, BALATON Zoltan wrote:

This is the rest of the MMU clean up series the first part of which
was merged. Here are the remaining patches rebased and some more added.


Besides cleaning up this code my other goal with this and previous already 
merged series was trying to optimise this a bit. Here are some numbers 
I've got with 9.0 compared to after this series. I've got these running 
old benchmarks that do a lot of memory accesses under AmigaOS on sam460ex 
and amigaone machines. The speed up is not much but measurable.


***
sam460ex:
QEMU v9.0.0
===
   Sieve of Eratosthenes (Scaled to 10 Iterations)
   Version 1.2, 03 April 1992

   Array Size   Number   Last PrimeLinear RunTimeMIPS
(Bytes)   of Primes   Time(sec)(Sec)
   8191   189916381   0.001068   0.001068  1552.2
  1   226119997   0.001304   0.001373  1479.5
  2   420239989   0.002608   0.002747  1498.7
  4   78367   0.005216   0.005493  1517.0
  8  14683   160001   0.010432   0.010681  1578.4
 16  27607   319993   0.020864   0.241089   141.4
 32  52073   639997   0.041728   0.79956186.2
 64  98609  1279997   0.083457   2.01904368.9
128 187133  2559989   0.166913   4.82421958.2
256 356243  5119997   0.333827  11.14257850.9
512 679460 10239989   0.667654  25.48828144.9
   10241299068 2047   1.335307  55.89843841.2
   20482488465 40960001   2.670614  125.62500037.0

   Average RunTime = 0.020496 (sec)
   High  MIPS  =   1578.4
   Low   MIPS  = 37.0

STREAM version $Revision: 5.10 $
Your clock granularity/precision appears to be 3 microseconds.
Each test below will take on the order of 228749 microseconds.
   (= 76249 clock ticks)
FunctionBest Rate MB/s  Avg time Min time Max time
Copy:1703.0 0.097710 0.093951 0.107887
Scale:706.9 0.233270 0.226353 0.244723
Add:  862.8 0.288949 0.278165 0.302902
Triad:763.4 0.318530 0.314394 0.324167

QEMU master + this series:
==
   Sieve of Eratosthenes (Scaled to 10 Iterations)
   Version 1.2, 03 April 1992

   Array Size   Number   Last PrimeLinear RunTimeMIPS
(Bytes)   of Primes   Time(sec)(Sec)
   8191   189916381   0.001068   0.001068  1552.2
  1   226119997   0.001304   0.001259  1614.0
  2   420239989   0.002608   0.002518  1635.0
  4   78367   0.005216   0.005493  1517.0
  8  14683   160001   0.010432   0.011597  1453.8
 16  27607   319993   0.020864   0.218506   156.0
 32  52073   639997   0.041728   0.74707092.2
 64  98609  1279997   0.083457   1.88720773.7
128 187133  2559989   0.166913   4.63378960.6
256 356243  5119997   0.333827  10.44921954.2
512 679460 10239989   0.667654  23.7548.1
   10241299068 2047   1.335307  52.10937544.2
   20482488465 40960001   2.670614  117.03125039.7

   Relative to 10 Iterations and the 8191 Array Size:
   Average RunTime = 0.019190 (sec)
   High  MIPS  =   1635.0
   Low   MIPS  = 39.7

STREAM version $Revision: 5.10 $
Your clock granularity/precision appears to be 3 microseconds.
Each test below will take on the order of 189202 microseconds.
   (= 63067 clock ticks)
FunctionBest Rate MB/s  Avg time Min time Max time
Copy:1730.8 0.096015 0.092444 0.107926
Scale:784.4 0.208925 0.203969 0.217610
Add: 1002.6 0.243805 0.239389 0.254176
Triad:768.9 0.322526 0.312154 0.345777

***
amigaone:
QEMU v9.0.0
===
   Sieve of Eratosthenes (Scaled to 10 Iterations)
   Version 1.2, 03 April 1992

   Array Size   Number   Last PrimeLinear RunTimeMIPS
(Bytes)   of Primes   Time(sec)(Sec)
   8191   189916381   0.001068   0.001068  1552.2
  1   226119997   0.001304   0.001259  1614.0
  2   420239989   0.002608   0.002747  1498.7
  4   78367   0.005216   0.005493  1517.0
  8  14683   160001   0.010432   0.010986  1534.6
 16  27607   319993   0.020864   0.023193  1469.7
 32  52073   639997   0.041728   0.047607  1446.9
 64  98609  1279997   0.083457   0.100098  1389.9
128 187133  2559989   0.166913   0.200195  1403.0
256 356243  5119997   0.333827   0.400391  1415.6
512 679460 10239989   0.667654   1.484375   770.2

[PATCH 29/43] target/ppc/mmu-hash32.c: Move get_pteg_offset32() to the header

2024-05-26 Thread BALATON Zoltan
This function is a simple shared function, move it to other similar
static inline functions in the header.

Signed-off-by: BALATON Zoltan 
---
 target/ppc/mmu-hash32.c | 7 ---
 target/ppc/mmu-hash32.h | 6 +-
 2 files changed, 5 insertions(+), 8 deletions(-)

diff --git a/target/ppc/mmu-hash32.c b/target/ppc/mmu-hash32.c
index c4de1647e2..44b16142ab 100644
--- a/target/ppc/mmu-hash32.c
+++ b/target/ppc/mmu-hash32.c
@@ -201,13 +201,6 @@ static bool ppc_hash32_direct_store(PowerPCCPU *cpu, 
target_ulong sr,
 return false;
 }
 
-hwaddr get_pteg_offset32(PowerPCCPU *cpu, hwaddr hash)
-{
-target_ulong mask = ppc_hash32_hpt_mask(cpu);
-
-return (hash * HASH_PTEG_SIZE_32) & mask;
-}
-
 static hwaddr ppc_hash32_pteg_search(PowerPCCPU *cpu, hwaddr pteg_off,
  bool secondary, target_ulong ptem,
  ppc_hash_pte32_t *pte)
diff --git a/target/ppc/mmu-hash32.h b/target/ppc/mmu-hash32.h
index bd75f7d647..2838de031c 100644
--- a/target/ppc/mmu-hash32.h
+++ b/target/ppc/mmu-hash32.h
@@ -3,7 +3,6 @@
 
 #ifndef CONFIG_USER_ONLY
 
-hwaddr get_pteg_offset32(PowerPCCPU *cpu, hwaddr hash);
 bool ppc_hash32_xlate(PowerPCCPU *cpu, vaddr eaddr, MMUAccessType access_type,
   hwaddr *raddrp, int *psizep, int *protp, int mmu_idx,
   bool guest_visible);
@@ -102,6 +101,11 @@ static inline void ppc_hash32_store_hpte1(PowerPCCPU *cpu,
 stl_phys(CPU(cpu)->as, base + pte_offset + HASH_PTE_SIZE_32 / 2, pte1);
 }
 
+static inline hwaddr get_pteg_offset32(PowerPCCPU *cpu, hwaddr hash)
+{
+return (hash * HASH_PTEG_SIZE_32) & ppc_hash32_hpt_mask(cpu);
+}
+
 static inline bool ppc_hash32_key(bool pr, target_ulong sr)
 {
 return pr ? (sr & SR32_KP) : (sr & SR32_KS);
-- 
2.30.9




[PATCH 31/43] target/ppc/mmu-radix64: Remove externally unused parts from header

2024-05-26 Thread BALATON Zoltan
Move the parts not needed outside of mmu-radix64.c from the header to
the C file to leave only parts in the header that need to be exported.
Also drop unneded include of this header.

Signed-off-by: BALATON Zoltan 
---
 target/ppc/mmu-book3s-v3.c |  1 -
 target/ppc/mmu-radix64.c   | 49 +++
 target/ppc/mmu-radix64.h   | 53 +-
 3 files changed, 50 insertions(+), 53 deletions(-)

diff --git a/target/ppc/mmu-book3s-v3.c b/target/ppc/mmu-book3s-v3.c
index c8f69b3df9..a812cb5113 100644
--- a/target/ppc/mmu-book3s-v3.c
+++ b/target/ppc/mmu-book3s-v3.c
@@ -21,7 +21,6 @@
 #include "cpu.h"
 #include "mmu-hash64.h"
 #include "mmu-book3s-v3.h"
-#include "mmu-radix64.h"
 
 bool ppc64_v3_get_pate(PowerPCCPU *cpu, target_ulong lpid, ppc_v3_pate_t 
*entry)
 {
diff --git a/target/ppc/mmu-radix64.c b/target/ppc/mmu-radix64.c
index 5a02e4963b..cf9619e847 100644
--- a/target/ppc/mmu-radix64.c
+++ b/target/ppc/mmu-radix64.c
@@ -29,6 +29,37 @@
 #include "mmu-radix64.h"
 #include "mmu-book3s-v3.h"
 
+/* Radix Partition Table Entry Fields */
+#define PATE1_R_PRTB   0x0000
+#define PATE1_R_PRTS   0x001F
+
+/* Radix Process Table Entry Fields */
+#define PRTBE_R_GET_RTS(rts) \
+rts >> 58) & 0x18) | ((rts >> 5) & 0x7)) + 31)
+#define PRTBE_R_RPDB0x0F00
+#define PRTBE_R_RPDS0x001F
+
+/* Radix Page Directory/Table Entry Fields */
+#define R_PTE_VALID 0x8000
+#define R_PTE_LEAF  0x4000
+#define R_PTE_SW0   0x2000
+#define R_PTE_RPN   0x01FFF000
+#define R_PTE_SW1   0x0E00
+#define R_GET_SW(sw)(((sw >> 58) & 0x8) | ((sw >> 9) & 0x7))
+#define R_PTE_R 0x0100
+#define R_PTE_C 0x0080
+#define R_PTE_ATT   0x0030
+#define R_PTE_ATT_NORMAL0x
+#define R_PTE_ATT_SAO   0x0010
+#define R_PTE_ATT_NI_IO 0x0020
+#define R_PTE_ATT_TOLERANT_IO   0x0030
+#define R_PTE_EAA_PRIV  0x0008
+#define R_PTE_EAA_R 0x0004
+#define R_PTE_EAA_RW0x0002
+#define R_PTE_EAA_X 0x0001
+#define R_PDE_NLB   PRTBE_R_RPDB
+#define R_PDE_NLS   PRTBE_R_RPDS
+
 static bool ppc_radix64_get_fully_qualified_addr(const CPUPPCState *env,
  vaddr eaddr,
  uint64_t *lpid, uint64_t *pid)
@@ -180,6 +211,24 @@ static void ppc_radix64_raise_hsi(PowerPCCPU *cpu, 
MMUAccessType access_type,
 }
 }
 
+static int ppc_radix64_get_prot_eaa(uint64_t pte)
+{
+return (pte & R_PTE_EAA_R ? PAGE_READ : 0) |
+   (pte & R_PTE_EAA_RW ? PAGE_READ | PAGE_WRITE : 0) |
+   (pte & R_PTE_EAA_X ? PAGE_EXEC : 0);
+}
+
+static int ppc_radix64_get_prot_amr(const PowerPCCPU *cpu)
+{
+const CPUPPCState *env = >env;
+int amr = env->spr[SPR_AMR] >> 62; /* We only care about key0 AMR63:62 */
+int iamr = env->spr[SPR_IAMR] >> 62; /* We only care about key0 IAMR63:62 
*/
+
+return (amr & 0x2 ? 0 : PAGE_WRITE) | /* Access denied if bit is set */
+   (amr & 0x1 ? 0 : PAGE_READ) |
+   (iamr & 0x1 ? 0 : PAGE_EXEC);
+}
+
 static bool ppc_radix64_check_prot(PowerPCCPU *cpu, MMUAccessType access_type,
uint64_t pte, int *fault_cause, int *prot,
int mmu_idx, bool partition_scoped)
diff --git a/target/ppc/mmu-radix64.h b/target/ppc/mmu-radix64.h
index c5c04a1527..6620b3d648 100644
--- a/target/ppc/mmu-radix64.h
+++ b/target/ppc/mmu-radix64.h
@@ -3,7 +3,7 @@
 
 #ifndef CONFIG_USER_ONLY
 
-#include "exec/page-protection.h"
+#ifdef TARGET_PPC64
 
 /* Radix Quadrants */
 #define R_EADDR_MASK0x3FFF
@@ -14,61 +14,10 @@
 #define R_EADDR_QUADRANT2   0x8000
 #define R_EADDR_QUADRANT3   0xC000
 
-/* Radix Partition Table Entry Fields */
-#define PATE1_R_PRTB   0x0000
-#define PATE1_R_PRTS   0x001F
-
-/* Radix Process Table Entry Fields */
-#define PRTBE_R_GET_RTS(rts) \
-rts >> 58) & 0x18) | ((rts >> 5) & 0x7)) + 31)
-#define PRTBE_R_RPDB0x0F00
-#define PRTBE_R_RPDS0x001F
-
-/* Radix Page Directory/Table Entry Fields */
-#define R_PTE_VALID 0x8000
-#define R_PTE_LEAF  0x4000
-#define R_PTE_SW0   0x2000
-#define R_PTE_RPN   0x01FFF000
-#define R_PTE_SW1 

[PATCH 41/43] target/ppc: Change MMU xlate functions to take CPUState

2024-05-26 Thread BALATON Zoltan
The callers of xlate functions get CPUState which is then cast to
PowerPCCPU that is then cast back to CPUState by most xlate functions.
Avoid this back and forth casting by passing the existing CPUState to
xlate functions and let them convert it as needed.

Signed-off-by: BALATON Zoltan 
---
 target/ppc/internal.h|  2 +-
 target/ppc/mmu-booke.c   |  5 ++--
 target/ppc/mmu-booke.h   |  2 +-
 target/ppc/mmu-hash32.c  |  4 +--
 target/ppc/mmu-hash32.h  |  2 +-
 target/ppc/mmu-hash64.c  |  4 +--
 target/ppc/mmu-hash64.h  |  2 +-
 target/ppc/mmu-radix64.c |  7 +++---
 target/ppc/mmu-radix64.h |  2 +-
 target/ppc/mmu_common.c  | 54 +++-
 target/ppc/mmu_helper.c  |  9 +++
 11 files changed, 45 insertions(+), 48 deletions(-)

diff --git a/target/ppc/internal.h b/target/ppc/internal.h
index 66ce22bbe9..753fae219c 100644
--- a/target/ppc/internal.h
+++ b/target/ppc/internal.h
@@ -251,7 +251,7 @@ static inline int check_prot_access_type(int prot, 
MMUAccessType access_type)
 
 /* PowerPC MMU emulation */
 
-bool ppc_xlate(PowerPCCPU *cpu, vaddr eaddr, MMUAccessType access_type,
+bool ppc_xlate(CPUState *cs, vaddr eaddr, MMUAccessType access_type,
   hwaddr *raddrp, int *psizep, int *protp,
   int mmu_idx, bool guest_visible);
 
diff --git a/target/ppc/mmu-booke.c b/target/ppc/mmu-booke.c
index 55e5dd7c6b..dd4ea48151 100644
--- a/target/ppc/mmu-booke.c
+++ b/target/ppc/mmu-booke.c
@@ -473,12 +473,11 @@ static void booke206_update_mas_tlb_miss(CPUPPCState 
*env, target_ulong address,
 env->spr[SPR_BOOKE_MAS0] |= env->last_way << MAS0_NV_SHIFT;
 }
 
-bool ppc_booke_xlate(PowerPCCPU *cpu, vaddr eaddr, MMUAccessType access_type,
+bool ppc_booke_xlate(CPUState *cs, vaddr eaddr, MMUAccessType access_type,
  hwaddr *raddrp, int *psizep, int *protp, int mmu_idx,
  bool guest_visible)
 {
-CPUState *cs = CPU(cpu);
-CPUPPCState *env = >env;
+CPUPPCState *env = cpu_env(cs);
 hwaddr raddr;
 int prot, ret;
 
diff --git a/target/ppc/mmu-booke.h b/target/ppc/mmu-booke.h
index f972843bbb..6c90139be0 100644
--- a/target/ppc/mmu-booke.h
+++ b/target/ppc/mmu-booke.h
@@ -10,7 +10,7 @@ int mmu40x_get_physical_address(CPUPPCState *env, hwaddr 
*raddr, int *prot,
 hwaddr booke206_tlb_to_page_size(CPUPPCState *env, ppcmas_tlb_t *tlb);
 int ppcmas_tlb_check(CPUPPCState *env, ppcmas_tlb_t *tlb, hwaddr *raddrp,
  target_ulong address, uint32_t pid);
-bool ppc_booke_xlate(PowerPCCPU *cpu, vaddr eaddr, MMUAccessType access_type,
+bool ppc_booke_xlate(CPUState *cs, vaddr eaddr, MMUAccessType access_type,
  hwaddr *raddrp, int *psizep, int *protp, int mmu_idx,
  bool guest_visible);
 
diff --git a/target/ppc/mmu-hash32.c b/target/ppc/mmu-hash32.c
index f18faf0f46..82a02881c2 100644
--- a/target/ppc/mmu-hash32.c
+++ b/target/ppc/mmu-hash32.c
@@ -279,11 +279,11 @@ static hwaddr ppc_hash32_htab_lookup(PowerPCCPU *cpu,
 return pte_addr;
 }
 
-bool ppc_hash32_xlate(PowerPCCPU *cpu, vaddr eaddr, MMUAccessType access_type,
+bool ppc_hash32_xlate(CPUState *cs, vaddr eaddr, MMUAccessType access_type,
   hwaddr *raddrp, int *psizep, int *protp, int mmu_idx,
   bool guest_visible)
 {
-CPUState *cs = CPU(cpu);
+PowerPCCPU *cpu = POWERPC_CPU(cs);
 CPUPPCState *env = >env;
 target_ulong sr;
 hwaddr pte_addr, raddr;
diff --git a/target/ppc/mmu-hash32.h b/target/ppc/mmu-hash32.h
index ec8d881def..d9e4977bdc 100644
--- a/target/ppc/mmu-hash32.h
+++ b/target/ppc/mmu-hash32.h
@@ -3,7 +3,7 @@
 
 #ifndef CONFIG_USER_ONLY
 
-bool ppc_hash32_xlate(PowerPCCPU *cpu, vaddr eaddr, MMUAccessType access_type,
+bool ppc_hash32_xlate(CPUState *cs, vaddr eaddr, MMUAccessType access_type,
   hwaddr *raddrp, int *psizep, int *protp, int mmu_idx,
   bool guest_visible);
 
diff --git a/target/ppc/mmu-hash64.c b/target/ppc/mmu-hash64.c
index 5e1983e334..1559683626 100644
--- a/target/ppc/mmu-hash64.c
+++ b/target/ppc/mmu-hash64.c
@@ -979,11 +979,11 @@ static int build_vrma_slbe(PowerPCCPU *cpu, ppc_slb_t 
*slb)
 return -1;
 }
 
-bool ppc_hash64_xlate(PowerPCCPU *cpu, vaddr eaddr, MMUAccessType access_type,
+bool ppc_hash64_xlate(CPUState *cs, vaddr eaddr, MMUAccessType access_type,
   hwaddr *raddrp, int *psizep, int *protp, int mmu_idx,
   bool guest_visible)
 {
-CPUState *cs = CPU(cpu);
+PowerPCCPU *cpu = POWERPC_CPU(cs);
 CPUPPCState *env = >env;
 ppc_slb_t vrma_slbe;
 ppc_slb_t *slb;
diff --git a/target/ppc/mmu-hash64.h b/target/ppc/mmu-hash64.h
index ae8d4b37ae..0c475642e0 100644
--- a/target/ppc/mmu-hash64.h
+++ b/target/ppc/mmu-hash64.h
@@ -7,7 +7,7 @@
 void dump_slb(PowerPCCPU *cpu);
 int ppc_store_slb(PowerPCCPU *cpu, target_ulong slot,
   target_ulong esid, targ

[PATCH 15/43] target/ppc/mmu_common.c: Simplify a switch statement

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

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

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




[PATCH 34/43] target/ppc/internal.h: Consolidate ifndef CONFIG_USER_ONLY blocks

2024-05-26 Thread BALATON Zoltan
A few pte related definitions are between two ifndef CONFIG_USER_ONLY
blocks but these are not needed for user only and should also be
within these blocks. Consolidate the ifndef blocks so all user only and
not user only definitions are in one #ifdef #else at the end of the file.

Signed-off-by: BALATON Zoltan 
---
 target/ppc/internal.h | 23 ++-
 1 file changed, 10 insertions(+), 13 deletions(-)

diff --git a/target/ppc/internal.h b/target/ppc/internal.h
index 8e5a241f74..66ce22bbe9 100644
--- a/target/ppc/internal.h
+++ b/target/ppc/internal.h
@@ -224,6 +224,10 @@ void helper_compute_fprf_float16(CPUPPCState *env, float16 
arg);
 void helper_compute_fprf_float32(CPUPPCState *env, float32 arg);
 void helper_compute_fprf_float128(CPUPPCState *env, float128 arg);
 
+FIELD(GER_MSK, XMSK, 0, 4)
+FIELD(GER_MSK, YMSK, 4, 4)
+FIELD(GER_MSK, PMSK, 8, 8)
+
 /* translate.c */
 
 int ppc_fixup_cpu(PowerPCCPU *cpu);
@@ -234,8 +238,11 @@ void destroy_ppc_opcodes(PowerPCCPU *cpu);
 void ppc_gdb_init(CPUState *cs, PowerPCCPUClass *ppc);
 const gchar *ppc_gdb_arch_name(CPUState *cs);
 
-#ifndef CONFIG_USER_ONLY
-
+#ifdef CONFIG_USER_ONLY
+void ppc_cpu_record_sigsegv(CPUState *cs, vaddr addr,
+MMUAccessType access_type,
+bool maperr, uintptr_t ra);
+#else
 /* Check if permission bit required for the access_type is set in prot */
 static inline int check_prot_access_type(int prot, MMUAccessType access_type)
 {
@@ -252,7 +259,6 @@ bool ppc_xlate(PowerPCCPU *cpu, vaddr eaddr, MMUAccessType 
access_type,
 int ppc6xx_tlb_getnum(CPUPPCState *env, target_ulong eaddr,
 int way, int is_code);
 
-#endif /* !CONFIG_USER_ONLY */
 
 /* Common routines used by software and hardware TLBs emulation */
 static inline int pte_is_valid(target_ulong pte0)
@@ -268,11 +274,6 @@ static inline void pte_invalidate(target_ulong *pte0)
 #define PTE_PTEM_MASK 0x7FBF
 #define PTE_CHECK_MASK (TARGET_PAGE_MASK | 0x7B)
 
-#ifdef CONFIG_USER_ONLY
-void ppc_cpu_record_sigsegv(CPUState *cs, vaddr addr,
-MMUAccessType access_type,
-bool maperr, uintptr_t ra);
-#else
 bool ppc_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
   MMUAccessType access_type, int mmu_idx,
   bool probe, uintptr_t retaddr);
@@ -287,10 +288,6 @@ void ppc_cpu_do_transaction_failed(CPUState *cs, hwaddr 
physaddr,
 void ppc_cpu_debug_excp_handler(CPUState *cs);
 bool ppc_cpu_debug_check_breakpoint(CPUState *cs);
 bool ppc_cpu_debug_check_watchpoint(CPUState *cs, CPUWatchpoint *wp);
-#endif
-
-FIELD(GER_MSK, XMSK, 0, 4)
-FIELD(GER_MSK, YMSK, 4, 4)
-FIELD(GER_MSK, PMSK, 8, 8)
+#endif /* !CONFIG_USER_ONLY */
 
 #endif /* PPC_INTERNAL_H */
-- 
2.30.9




[PATCH 43/43] target/ppc/mmu-hash32.c: Change parameter type of ppc_hash32_direct_store

2024-05-26 Thread BALATON Zoltan
This function needs CPUState and env but takes PowerPCCPU and cast
that. We already have the right types in the caller so pass them to
this function to avoid casting.

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

diff --git a/target/ppc/mmu-hash32.c b/target/ppc/mmu-hash32.c
index 0f9c61bf89..3588f8f8de 100644
--- a/target/ppc/mmu-hash32.c
+++ b/target/ppc/mmu-hash32.c
@@ -109,15 +109,12 @@ static hwaddr ppc_hash32_bat_lookup(CPUPPCState *env, 
target_ulong ea,
 return -1;
 }
 
-static bool ppc_hash32_direct_store(PowerPCCPU *cpu, target_ulong sr,
-target_ulong eaddr,
+static bool ppc_hash32_direct_store(CPUState *cs, CPUPPCState *env,
+target_ulong sr, target_ulong eaddr,
 MMUAccessType access_type,
 hwaddr *raddr, int *prot, int mmu_idx,
 bool guest_visible)
 {
-CPUState *cs = CPU(cpu);
-CPUPPCState *env = >env;
-
 qemu_log_mask(CPU_LOG_MMU, "direct store...\n");
 
 if (access_type == MMU_INST_FETCH) {
@@ -336,7 +333,7 @@ bool ppc_hash32_xlate(CPUState *cs, vaddr eaddr, 
MMUAccessType access_type,
 
 /* 4. Handle direct store segments */
 if (sr & SR32_T) {
-return ppc_hash32_direct_store(cpu, sr, eaddr, access_type,
+return ppc_hash32_direct_store(cs, env, sr, eaddr, access_type,
raddrp, protp, mmu_idx, guest_visible);
 }
 
-- 
2.30.9




[PATCH 10/43] target/ppc/mmu_common.c: Remove hash field from mmu_ctx_t

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

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

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




[PATCH 16/43] target/ppc/mmu_common.c: Inline and remove ppc6xx_tlb_pte_check()

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

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

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




[PATCH 11/43] target/ppc/mmu_common.c: Remove pte_update_flags()

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

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

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




[PATCH 37/43] target/ppc/mmu-hash32.c: Return and use pte address instead of base + offset

2024-05-26 Thread BALATON Zoltan
Change ppc_hash32_pteg_search() to return pte address instead of an
offset to avoid needing to get the base and add offset to it when we
already have the address we need.

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

diff --git a/target/ppc/mmu-hash32.c b/target/ppc/mmu-hash32.c
index 7a6a674f8a..cc1e790d0e 100644
--- a/target/ppc/mmu-hash32.c
+++ b/target/ppc/mmu-hash32.c
@@ -204,58 +204,48 @@ static hwaddr ppc_hash32_pteg_search(PowerPCCPU *cpu, 
hwaddr pteg_off,
  bool secondary, target_ulong ptem,
  ppc_hash_pte32_t *pte)
 {
-hwaddr pte_offset = pteg_off;
+hwaddr pte_addr = ppc_hash32_hpt_base(cpu) + pteg_off;
 target_ulong pte0, pte1;
-hwaddr base = ppc_hash32_hpt_base(cpu);
 int i;
 
-for (i = 0; i < HPTES_PER_GROUP; i++) {
-pte0 = ldl_phys(CPU(cpu)->as, base + pte_offset);
+for (i = 0; i < HPTES_PER_GROUP; i++, pte_addr += HASH_PTE_SIZE_32) {
+pte0 = ldl_phys(CPU(cpu)->as, pte_addr);
 /*
  * pte0 contains the valid bit and must be read before pte1,
  * otherwise we might see an old pte1 with a new valid bit and
  * thus an inconsistent hpte value
  */
 smp_rmb();
-pte1 = ldl_phys(CPU(cpu)->as, base + pte_offset + HASH_PTE_SIZE_32 / 
2);
+pte1 = ldl_phys(CPU(cpu)->as, pte_addr + HASH_PTE_SIZE_32 / 2);
 
 if ((pte0 & HPTE32_V_VALID)
 && (secondary == !!(pte0 & HPTE32_V_SECONDARY))
 && HPTE32_V_COMPARE(pte0, ptem)) {
 pte->pte0 = pte0;
 pte->pte1 = pte1;
-return pte_offset;
+return pte_addr;
 }
-
-pte_offset += HASH_PTE_SIZE_32;
 }
-
 return -1;
 }
 
-static void ppc_hash32_set_r(PowerPCCPU *cpu, hwaddr pte_offset, uint32_t pte1)
+static void ppc_hash32_set_r(PowerPCCPU *cpu, hwaddr pte_addr, uint32_t pte1)
 {
-target_ulong base = ppc_hash32_hpt_base(cpu);
-hwaddr offset = pte_offset + 6;
-
 /* The HW performs a non-atomic byte update */
-stb_phys(CPU(cpu)->as, base + offset, ((pte1 >> 8) & 0xff) | 0x01);
+stb_phys(CPU(cpu)->as, pte_addr + 6, ((pte1 >> 8) & 0xff) | 0x01);
 }
 
-static void ppc_hash32_set_c(PowerPCCPU *cpu, hwaddr pte_offset, uint64_t pte1)
+static void ppc_hash32_set_c(PowerPCCPU *cpu, hwaddr pte_addr, uint64_t pte1)
 {
-target_ulong base = ppc_hash32_hpt_base(cpu);
-hwaddr offset = pte_offset + 7;
-
 /* The HW performs a non-atomic byte update */
-stb_phys(CPU(cpu)->as, base + offset, (pte1 & 0xff) | 0x80);
+stb_phys(CPU(cpu)->as, pte_addr + 7, (pte1 & 0xff) | 0x80);
 }
 
 static hwaddr ppc_hash32_htab_lookup(PowerPCCPU *cpu,
  target_ulong sr, target_ulong eaddr,
  ppc_hash_pte32_t *pte)
 {
-hwaddr pteg_off, pte_offset;
+hwaddr pteg_off, pte_addr;
 hwaddr hash;
 uint32_t vsid, pgidx, ptem;
 
@@ -277,18 +267,18 @@ static hwaddr ppc_hash32_htab_lookup(PowerPCCPU *cpu,
 ppc_hash32_hpt_base(cpu), ppc_hash32_hpt_mask(cpu),
 vsid, ptem, hash);
 pteg_off = get_pteg_offset32(cpu, hash);
-pte_offset = ppc_hash32_pteg_search(cpu, pteg_off, 0, ptem, pte);
-if (pte_offset == -1) {
+pte_addr = ppc_hash32_pteg_search(cpu, pteg_off, 0, ptem, pte);
+if (pte_addr == -1) {
 /* Secondary PTEG lookup */
 qemu_log_mask(CPU_LOG_MMU, "1 htab=" HWADDR_FMT_plx "/" HWADDR_FMT_plx
 " vsid=%" PRIx32 " api=%" PRIx32
 " hash=" HWADDR_FMT_plx "\n", ppc_hash32_hpt_base(cpu),
 ppc_hash32_hpt_mask(cpu), vsid, ptem, ~hash);
 pteg_off = get_pteg_offset32(cpu, ~hash);
-pte_offset = ppc_hash32_pteg_search(cpu, pteg_off, 1, ptem, pte);
+pte_addr = ppc_hash32_pteg_search(cpu, pteg_off, 1, ptem, pte);
 }
 
-return pte_offset;
+return pte_addr;
 }
 
 bool ppc_hash32_xlate(PowerPCCPU *cpu, vaddr eaddr, MMUAccessType access_type,
@@ -298,7 +288,7 @@ bool ppc_hash32_xlate(PowerPCCPU *cpu, vaddr eaddr, 
MMUAccessType access_type,
 CPUState *cs = CPU(cpu);
 CPUPPCState *env = >env;
 target_ulong sr;
-hwaddr pte_offset, raddr;
+hwaddr pte_addr, raddr;
 ppc_hash_pte32_t pte;
 bool key;
 int prot;
@@ -360,8 +350,8 @@ bool ppc_hash32_xlate(PowerPCCPU *cpu, vaddr eaddr, 
MMUAccessType access_type,
 }
 
 /* 6. Locate the PTE in the hash table */
-pte_offset = ppc_hash32_htab_lookup(cpu, sr, eaddr, );
-if (pte_offset == -1) {
+pte_addr = ppc_hash32_htab_lookup(cpu, sr, eaddr, );
+if (pte_addr == -1) {
 if (guest_visible) {
 if (access_type == MMU_INST_F

[PATCH 36/43] target/ppc/mmu-hash32: Remove some static inlines from header

2024-05-26 Thread BALATON Zoltan
Two of these are not used anywhere and the other two are used only
once and can be inlined and removed from the header.

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

diff --git a/target/ppc/mmu-hash32.c b/target/ppc/mmu-hash32.c
index a2c0ac05d2..7a6a674f8a 100644
--- a/target/ppc/mmu-hash32.c
+++ b/target/ppc/mmu-hash32.c
@@ -206,17 +206,18 @@ static hwaddr ppc_hash32_pteg_search(PowerPCCPU *cpu, 
hwaddr pteg_off,
 {
 hwaddr pte_offset = pteg_off;
 target_ulong pte0, pte1;
+hwaddr base = ppc_hash32_hpt_base(cpu);
 int i;
 
 for (i = 0; i < HPTES_PER_GROUP; i++) {
-pte0 = ppc_hash32_load_hpte0(cpu, pte_offset);
+pte0 = ldl_phys(CPU(cpu)->as, base + pte_offset);
 /*
  * pte0 contains the valid bit and must be read before pte1,
  * otherwise we might see an old pte1 with a new valid bit and
  * thus an inconsistent hpte value
  */
 smp_rmb();
-pte1 = ppc_hash32_load_hpte1(cpu, pte_offset);
+pte1 = ldl_phys(CPU(cpu)->as, base + pte_offset + HASH_PTE_SIZE_32 / 
2);
 
 if ((pte0 & HPTE32_V_VALID)
 && (secondary == !!(pte0 & HPTE32_V_SECONDARY))
diff --git a/target/ppc/mmu-hash32.h b/target/ppc/mmu-hash32.h
index 2838de031c..4db55fb0a0 100644
--- a/target/ppc/mmu-hash32.h
+++ b/target/ppc/mmu-hash32.h
@@ -69,38 +69,6 @@ static inline hwaddr ppc_hash32_hpt_mask(PowerPCCPU *cpu)
 return ((cpu->env.spr[SPR_SDR1] & SDR_32_HTABMASK) << 16) | 0x;
 }
 
-static inline target_ulong ppc_hash32_load_hpte0(PowerPCCPU *cpu,
- hwaddr pte_offset)
-{
-target_ulong base = ppc_hash32_hpt_base(cpu);
-
-return ldl_phys(CPU(cpu)->as, base + pte_offset);
-}
-
-static inline target_ulong ppc_hash32_load_hpte1(PowerPCCPU *cpu,
- hwaddr pte_offset)
-{
-target_ulong base = ppc_hash32_hpt_base(cpu);
-
-return ldl_phys(CPU(cpu)->as, base + pte_offset + HASH_PTE_SIZE_32 / 2);
-}
-
-static inline void ppc_hash32_store_hpte0(PowerPCCPU *cpu,
-  hwaddr pte_offset, target_ulong pte0)
-{
-target_ulong base = ppc_hash32_hpt_base(cpu);
-
-stl_phys(CPU(cpu)->as, base + pte_offset, pte0);
-}
-
-static inline void ppc_hash32_store_hpte1(PowerPCCPU *cpu,
-  hwaddr pte_offset, target_ulong pte1)
-{
-target_ulong base = ppc_hash32_hpt_base(cpu);
-
-stl_phys(CPU(cpu)->as, base + pte_offset + HASH_PTE_SIZE_32 / 2, pte1);
-}
-
 static inline hwaddr get_pteg_offset32(PowerPCCPU *cpu, hwaddr hash)
 {
 return (hash * HASH_PTEG_SIZE_32) & ppc_hash32_hpt_mask(cpu);
-- 
2.30.9




[PATCH 27/43] target/ppc/mmu_common.c: Remove mmu_ctx_t

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

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

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




[PATCH 33/43] target/ppc: Remove single use static inline function

2024-05-26 Thread BALATON Zoltan
The ger_pack_masks() function is only used once and the inverse of
this operation is already inlined so it can be inlined too in the only
caller and removed from the header.

Signed-off-by: BALATON Zoltan 
---
 target/ppc/internal.h   | 9 -
 target/ppc/translate/vsx-impl.c.inc | 6 --
 2 files changed, 4 insertions(+), 11 deletions(-)

diff --git a/target/ppc/internal.h b/target/ppc/internal.h
index 20fb2ec593..8e5a241f74 100644
--- a/target/ppc/internal.h
+++ b/target/ppc/internal.h
@@ -293,13 +293,4 @@ FIELD(GER_MSK, XMSK, 0, 4)
 FIELD(GER_MSK, YMSK, 4, 4)
 FIELD(GER_MSK, PMSK, 8, 8)
 
-static inline int ger_pack_masks(int pmsk, int ymsk, int xmsk)
-{
-int msk = 0;
-msk = FIELD_DP32(msk, GER_MSK, XMSK, xmsk);
-msk = FIELD_DP32(msk, GER_MSK, YMSK, ymsk);
-msk = FIELD_DP32(msk, GER_MSK, PMSK, pmsk);
-return msk;
-}
-
 #endif /* PPC_INTERNAL_H */
diff --git a/target/ppc/translate/vsx-impl.c.inc 
b/target/ppc/translate/vsx-impl.c.inc
index 0266f09119..62950d348a 100644
--- a/target/ppc/translate/vsx-impl.c.inc
+++ b/target/ppc/translate/vsx-impl.c.inc
@@ -2819,7 +2819,7 @@ static bool trans_XXSETACCZ(DisasContext *ctx, arg_X_a *a)
 static bool do_ger(DisasContext *ctx, arg_MMIRR_XX3 *a,
 void (*helper)(TCGv_env, TCGv_ptr, TCGv_ptr, TCGv_ptr, TCGv_i32))
 {
-uint32_t mask;
+uint32_t mask = 0;
 TCGv_ptr xt, xa, xb;
 REQUIRE_INSNS_FLAGS2(ctx, ISA310);
 REQUIRE_VSX(ctx);
@@ -2832,7 +2832,9 @@ static bool do_ger(DisasContext *ctx, arg_MMIRR_XX3 *a,
 xa = gen_vsr_ptr(a->xa);
 xb = gen_vsr_ptr(a->xb);
 
-mask = ger_pack_masks(a->pmsk, a->ymsk, a->xmsk);
+mask = FIELD_DP32(mask, GER_MSK, XMSK, a->xmsk);
+mask = FIELD_DP32(mask, GER_MSK, YMSK, a->ymsk);
+mask = FIELD_DP32(mask, GER_MSK, PMSK, a->pmsk);
 helper(tcg_env, xa, xb, xt, tcg_constant_i32(mask));
 return true;
 }
-- 
2.30.9




[PATCH 32/43] target/ppc: Remove includes from mmu-book3s-v3.h

2024-05-26 Thread BALATON Zoltan
Drop includes from header that is not needed by the header itself and
only include them from C files that really need it.

Signed-off-by: BALATON Zoltan 
---
 target/ppc/mmu-book3s-v3.h | 3 ---
 target/ppc/mmu-hash64.c| 1 +
 target/ppc/mmu-radix64.c   | 1 +
 3 files changed, 2 insertions(+), 3 deletions(-)

diff --git a/target/ppc/mmu-book3s-v3.h b/target/ppc/mmu-book3s-v3.h
index 263ce55c1f..be66e26604 100644
--- a/target/ppc/mmu-book3s-v3.h
+++ b/target/ppc/mmu-book3s-v3.h
@@ -20,9 +20,6 @@
 #ifndef PPC_MMU_BOOK3S_V3_H
 #define PPC_MMU_BOOK3S_V3_H
 
-#include "mmu-hash64.h"
-#include "mmu-books.h"
-
 #ifndef CONFIG_USER_ONLY
 
 /*
diff --git a/target/ppc/mmu-hash64.c b/target/ppc/mmu-hash64.c
index 7bc0323f26..5e1983e334 100644
--- a/target/ppc/mmu-hash64.c
+++ b/target/ppc/mmu-hash64.c
@@ -31,6 +31,7 @@
 #include "hw/hw.h"
 #include "internal.h"
 #include "mmu-book3s-v3.h"
+#include "mmu-books.h"
 #include "helper_regs.h"
 
 #ifdef CONFIG_TCG
diff --git a/target/ppc/mmu-radix64.c b/target/ppc/mmu-radix64.c
index cf9619e847..be7a45f254 100644
--- a/target/ppc/mmu-radix64.c
+++ b/target/ppc/mmu-radix64.c
@@ -28,6 +28,7 @@
 #include "internal.h"
 #include "mmu-radix64.h"
 #include "mmu-book3s-v3.h"
+#include "mmu-books.h"
 
 /* Radix Partition Table Entry Fields */
 #define PATE1_R_PRTB   0x0000
-- 
2.30.9




[PATCH 04/43] target/ppc/mmu_common.c: Remove single use local variable

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

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

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




[PATCH 38/43] target/ppc/mmu-hash32.c: Use pte address as parameter instead of offset

2024-05-26 Thread BALATON Zoltan
Instead of getting base and adding an offset to it pass pte address to
ppc_hash32_pteg_search() that the only caller of this function already
has and can easily pass it. Also add a local variable in the caller to
avoid getting base multiple times.

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

diff --git a/target/ppc/mmu-hash32.c b/target/ppc/mmu-hash32.c
index cc1e790d0e..6d0adf3357 100644
--- a/target/ppc/mmu-hash32.c
+++ b/target/ppc/mmu-hash32.c
@@ -200,11 +200,10 @@ static bool ppc_hash32_direct_store(PowerPCCPU *cpu, 
target_ulong sr,
 return false;
 }
 
-static hwaddr ppc_hash32_pteg_search(PowerPCCPU *cpu, hwaddr pteg_off,
+static hwaddr ppc_hash32_pteg_search(PowerPCCPU *cpu, hwaddr pte_addr,
  bool secondary, target_ulong ptem,
  ppc_hash_pte32_t *pte)
 {
-hwaddr pte_addr = ppc_hash32_hpt_base(cpu) + pteg_off;
 target_ulong pte0, pte1;
 int i;
 
@@ -245,37 +244,35 @@ static hwaddr ppc_hash32_htab_lookup(PowerPCCPU *cpu,
  target_ulong sr, target_ulong eaddr,
  ppc_hash_pte32_t *pte)
 {
-hwaddr pteg_off, pte_addr;
-hwaddr hash;
+hwaddr hpt_base, pteg_off, pte_addr, hash;
 uint32_t vsid, pgidx, ptem;
 
+hpt_base = ppc_hash32_hpt_base(cpu);
 vsid = sr & SR32_VSID;
 pgidx = (eaddr & ~SEGMENT_MASK_256M) >> TARGET_PAGE_BITS;
 hash = vsid ^ pgidx;
 ptem = (vsid << 7) | (pgidx >> 10);
 
 /* Page address translation */
-qemu_log_mask(CPU_LOG_MMU, "htab_base " HWADDR_FMT_plx
-" htab_mask " HWADDR_FMT_plx
-" hash " HWADDR_FMT_plx "\n",
-ppc_hash32_hpt_base(cpu), ppc_hash32_hpt_mask(cpu), hash);
+qemu_log_mask(CPU_LOG_MMU, "htab_base " HWADDR_FMT_plx " htab_mask "
+  HWADDR_FMT_plx " hash " HWADDR_FMT_plx "\n",
+  hpt_base, ppc_hash32_hpt_mask(cpu), hash);
 
 /* Primary PTEG lookup */
 qemu_log_mask(CPU_LOG_MMU, "0 htab=" HWADDR_FMT_plx "/" HWADDR_FMT_plx
-" vsid=%" PRIx32 " ptem=%" PRIx32
-" hash=" HWADDR_FMT_plx "\n",
-ppc_hash32_hpt_base(cpu), ppc_hash32_hpt_mask(cpu),
-vsid, ptem, hash);
+  " vsid=%" PRIx32 " ptem=%" PRIx32 " hash=" HWADDR_FMT_plx
+  "\n", hpt_base, ppc_hash32_hpt_mask(cpu), vsid, ptem, hash);
 pteg_off = get_pteg_offset32(cpu, hash);
-pte_addr = ppc_hash32_pteg_search(cpu, pteg_off, 0, ptem, pte);
+pte_addr = ppc_hash32_pteg_search(cpu, hpt_base + pteg_off, 0, ptem, pte);
 if (pte_addr == -1) {
 /* Secondary PTEG lookup */
 qemu_log_mask(CPU_LOG_MMU, "1 htab=" HWADDR_FMT_plx "/" HWADDR_FMT_plx
-" vsid=%" PRIx32 " api=%" PRIx32
-" hash=" HWADDR_FMT_plx "\n", ppc_hash32_hpt_base(cpu),
-ppc_hash32_hpt_mask(cpu), vsid, ptem, ~hash);
+  " vsid=%" PRIx32 " api=%" PRIx32 " hash=" HWADDR_FMT_plx
+  "\n", hpt_base, ppc_hash32_hpt_mask(cpu), vsid, ptem,
+  ~hash);
 pteg_off = get_pteg_offset32(cpu, ~hash);
-pte_addr = ppc_hash32_pteg_search(cpu, pteg_off, 1, ptem, pte);
+pte_addr = ppc_hash32_pteg_search(cpu, hpt_base + pteg_off, 1, ptem,
+  pte);
 }
 
 return pte_addr;
-- 
2.30.9




[PATCH 17/43] target/ppc/mmu_common.c: Remove ptem field from mmu_ctx_t

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

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

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




[PATCH 12/43] target/ppc/mmu_common.c: Remove nx field from mmu_ctx_t

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

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

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




[PATCH 30/43] target/ppc: Unexport some functions from mmu-book3s-v3.h

2024-05-26 Thread BALATON Zoltan
The ppc_hash64_hpt_base() and ppc_hash64_hpt_mask() functions are
mostly used by mmu-hash64.c only but there is one call to
ppc_hash64_hpt_mask() in hw/ppc/spapr_vhyp_mmu.c.in a helper function
that can be moved to mmu-hash64.c which allows these functions to be
removed from the header.

Signed-off-by: BALATON Zoltan 
---
 hw/ppc/spapr_vhyp_mmu.c| 21 
 target/ppc/mmu-book3s-v3.h | 40 ---
 target/ppc/mmu-hash64.c| 49 ++
 target/ppc/mmu-hash64.h|  1 +
 4 files changed, 54 insertions(+), 57 deletions(-)

diff --git a/hw/ppc/spapr_vhyp_mmu.c b/hw/ppc/spapr_vhyp_mmu.c
index b3dd8b3a59..2d41d7f77b 100644
--- a/hw/ppc/spapr_vhyp_mmu.c
+++ b/hw/ppc/spapr_vhyp_mmu.c
@@ -15,19 +15,6 @@
 #include "helper_regs.h"
 #include "hw/ppc/spapr.h"
 #include "mmu-hash64.h"
-#include "mmu-book3s-v3.h"
-
-
-static inline bool valid_ptex(PowerPCCPU *cpu, target_ulong ptex)
-{
-/*
- * hash value/pteg group index is normalized by HPT mask
- */
-if (((ptex & ~7ULL) / HPTES_PER_GROUP) & ~ppc_hash64_hpt_mask(cpu)) {
-return false;
-}
-return true;
-}
 
 static target_ulong h_enter(PowerPCCPU *cpu, SpaprMachineState *spapr,
 target_ulong opcode, target_ulong *args)
@@ -70,7 +57,7 @@ static target_ulong h_enter(PowerPCCPU *cpu, 
SpaprMachineState *spapr,
 
 pteh &= ~0x60ULL;
 
-if (!valid_ptex(cpu, ptex)) {
+if (!ppc_hash64_valid_ptex(cpu, ptex)) {
 return H_PARAMETER;
 }
 
@@ -119,7 +106,7 @@ static RemoveResult remove_hpte(PowerPCCPU *cpu
 const ppc_hash_pte64_t *hptes;
 target_ulong v, r;
 
-if (!valid_ptex(cpu, ptex)) {
+if (!ppc_hash64_valid_ptex(cpu, ptex)) {
 return REMOVE_PARM;
 }
 
@@ -250,7 +237,7 @@ static target_ulong h_protect(PowerPCCPU *cpu, 
SpaprMachineState *spapr,
 const ppc_hash_pte64_t *hptes;
 target_ulong v, r;
 
-if (!valid_ptex(cpu, ptex)) {
+if (!ppc_hash64_valid_ptex(cpu, ptex)) {
 return H_PARAMETER;
 }
 
@@ -287,7 +274,7 @@ static target_ulong h_read(PowerPCCPU *cpu, 
SpaprMachineState *spapr,
 int i, ridx, n_entries = 1;
 const ppc_hash_pte64_t *hptes;
 
-if (!valid_ptex(cpu, ptex)) {
+if (!ppc_hash64_valid_ptex(cpu, ptex)) {
 return H_PARAMETER;
 }
 
diff --git a/target/ppc/mmu-book3s-v3.h b/target/ppc/mmu-book3s-v3.h
index f3f7993958..263ce55c1f 100644
--- a/target/ppc/mmu-book3s-v3.h
+++ b/target/ppc/mmu-book3s-v3.h
@@ -83,46 +83,6 @@ static inline bool ppc64_v3_radix(PowerPCCPU *cpu)
 return !!(cpu->env.spr[SPR_LPCR] & LPCR_HR);
 }
 
-static inline hwaddr ppc_hash64_hpt_base(PowerPCCPU *cpu)
-{
-uint64_t base;
-
-if (cpu->vhyp) {
-return 0;
-}
-if (cpu->env.mmu_model == POWERPC_MMU_3_00) {
-ppc_v3_pate_t pate;
-
-if (!ppc64_v3_get_pate(cpu, cpu->env.spr[SPR_LPIDR], )) {
-return 0;
-}
-base = pate.dw0;
-} else {
-base = cpu->env.spr[SPR_SDR1];
-}
-return base & SDR_64_HTABORG;
-}
-
-static inline hwaddr ppc_hash64_hpt_mask(PowerPCCPU *cpu)
-{
-uint64_t base;
-
-if (cpu->vhyp) {
-return cpu->vhyp_class->hpt_mask(cpu->vhyp);
-}
-if (cpu->env.mmu_model == POWERPC_MMU_3_00) {
-ppc_v3_pate_t pate;
-
-if (!ppc64_v3_get_pate(cpu, cpu->env.spr[SPR_LPIDR], )) {
-return 0;
-}
-base = pate.dw0;
-} else {
-base = cpu->env.spr[SPR_SDR1];
-}
-return (1ULL << ((base & SDR_64_HTABSIZE) + 18 - 7)) - 1;
-}
-
 #endif /* TARGET_PPC64 */
 
 #endif /* CONFIG_USER_ONLY */
diff --git a/target/ppc/mmu-hash64.c b/target/ppc/mmu-hash64.c
index cbc8efa0c3..7bc0323f26 100644
--- a/target/ppc/mmu-hash64.c
+++ b/target/ppc/mmu-hash64.c
@@ -508,6 +508,46 @@ static int ppc_hash64_amr_prot(PowerPCCPU *cpu, 
ppc_hash_pte64_t pte)
 return prot;
 }
 
+static hwaddr ppc_hash64_hpt_base(PowerPCCPU *cpu)
+{
+uint64_t base;
+
+if (cpu->vhyp) {
+return 0;
+}
+if (cpu->env.mmu_model == POWERPC_MMU_3_00) {
+ppc_v3_pate_t pate;
+
+if (!ppc64_v3_get_pate(cpu, cpu->env.spr[SPR_LPIDR], )) {
+return 0;
+}
+base = pate.dw0;
+} else {
+base = cpu->env.spr[SPR_SDR1];
+}
+return base & SDR_64_HTABORG;
+}
+
+static hwaddr ppc_hash64_hpt_mask(PowerPCCPU *cpu)
+{
+uint64_t base;
+
+if (cpu->vhyp) {
+return cpu->vhyp_class->hpt_mask(cpu->vhyp);
+}
+if (cpu->env.mmu_model == POWERPC_MMU_3_00) {
+ppc_v3_pate_t pate;
+
+if (!ppc64_v3_get_pate(cpu, cpu->env.spr[SPR_LPIDR], )) {
+return 0;
+}
+base = pate.dw0;
+} else {
+base = cpu->env.spr[SPR_SDR1];
+}
+return (1ULL << ((base & SDR_64_HTABSIZE) + 18 - 7)

[PATCH 25/43] target/ppc: Remove bat_size_prot()

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

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

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

[PATCH 02/43] target/ppc/mmu_common.c: Remove local name for a constant

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

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

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




[PATCH 42/43] target/ppc/mmu-hash32.c: Change parameter type of ppc_hash32_set_[rc]

2024-05-26 Thread BALATON Zoltan
These functions need AddressSpace from CPUState but take PowerPCCPU
instead and cast that. We have the right type in the caller so change
the parameter type and pass the needed value to avoid casting.

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

diff --git a/target/ppc/mmu-hash32.c b/target/ppc/mmu-hash32.c
index 82a02881c2..0f9c61bf89 100644
--- a/target/ppc/mmu-hash32.c
+++ b/target/ppc/mmu-hash32.c
@@ -228,16 +228,18 @@ static hwaddr ppc_hash32_pteg_search(PowerPCCPU *cpu, 
hwaddr pte_addr,
 return -1;
 }
 
-static void ppc_hash32_set_r(PowerPCCPU *cpu, hwaddr pte_addr, uint32_t pte1)
+static void ppc_hash32_set_r(AddressSpace *cpu_as, hwaddr pte_addr,
+ uint32_t pte1)
 {
 /* The HW performs a non-atomic byte update */
-stb_phys(CPU(cpu)->as, pte_addr + 6, ((pte1 >> 8) & 0xff) | 0x01);
+stb_phys(cpu_as, pte_addr + 6, ((pte1 >> 8) & 0xff) | 0x01);
 }
 
-static void ppc_hash32_set_c(PowerPCCPU *cpu, hwaddr pte_addr, uint64_t pte1)
+static void ppc_hash32_set_c(AddressSpace *cpu_as, hwaddr pte_addr,
+ uint64_t pte1)
 {
 /* The HW performs a non-atomic byte update */
-stb_phys(CPU(cpu)->as, pte_addr + 7, (pte1 & 0xff) | 0x80);
+stb_phys(cpu_as, pte_addr + 7, (pte1 & 0xff) | 0x80);
 }
 
 static hwaddr ppc_hash32_htab_lookup(PowerPCCPU *cpu,
@@ -399,11 +401,11 @@ bool ppc_hash32_xlate(CPUState *cs, vaddr eaddr, 
MMUAccessType access_type,
 
 /* 8. Update PTE referenced and changed bits if necessary */
 if (!(pte.pte1 & HPTE32_R_R)) {
-ppc_hash32_set_r(cpu, pte_addr, pte.pte1);
+ppc_hash32_set_r(cs->as, pte_addr, pte.pte1);
 }
 if (!(pte.pte1 & HPTE32_R_C)) {
 if (access_type == MMU_DATA_STORE) {
-ppc_hash32_set_c(cpu, pte_addr, pte.pte1);
+ppc_hash32_set_c(cs->as, pte_addr, pte.pte1);
 } else {
 /*
  * Treat the page as read-only for now, so that a later write
-- 
2.30.9




[PATCH 22/43] target/ppc/mmu_common.c: Stop using ctx in ppc6xx_tlb_check()

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

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

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




[PATCH 28/43] target/ppc/mmu-hash32.c: Inline and remove ppc_hash32_pte_raddr()

2024-05-26 Thread BALATON Zoltan
This function is used only once and does not add more clarity than
doing it inline.

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

diff --git a/target/ppc/mmu-hash32.c b/target/ppc/mmu-hash32.c
index 6f0f0bbb00..c4de1647e2 100644
--- a/target/ppc/mmu-hash32.c
+++ b/target/ppc/mmu-hash32.c
@@ -298,15 +298,6 @@ static hwaddr ppc_hash32_htab_lookup(PowerPCCPU *cpu,
 return pte_offset;
 }
 
-static hwaddr ppc_hash32_pte_raddr(target_ulong sr, ppc_hash_pte32_t pte,
-   target_ulong eaddr)
-{
-hwaddr rpn = pte.pte1 & HPTE32_R_RPN;
-hwaddr mask = ~TARGET_PAGE_MASK;
-
-return (rpn & ~mask) | (eaddr & mask);
-}
-
 bool ppc_hash32_xlate(PowerPCCPU *cpu, vaddr eaddr, MMUAccessType access_type,
   hwaddr *raddrp, int *psizep, int *protp, int mmu_idx,
   bool guest_visible)
@@ -440,11 +431,12 @@ bool ppc_hash32_xlate(PowerPCCPU *cpu, vaddr eaddr, 
MMUAccessType access_type,
  */
 prot &= ~PAGE_WRITE;
 }
- }
+}
+*protp = prot;
 
 /* 9. Determine the real address from the PTE */
-
-*raddrp = ppc_hash32_pte_raddr(sr, pte, eaddr);
-*protp = prot;
+*raddrp = pte.pte1 & HPTE32_R_RPN;
+*raddrp &= TARGET_PAGE_MASK;
+*raddrp |= eaddr & ~TARGET_PAGE_MASK;
 return true;
 }
-- 
2.30.9




[PATCH 01/43] target/ppc: Reorganise and rename ppc_hash32_pp_prot()

2024-05-26 Thread BALATON Zoltan
Reorganise ppc_hash32_pp_prot() swapping the if legs so it does not
test for negative first and clean up to make it shorter. Also rename
it to ppc_hash32_prot().

Signed-off-by: BALATON Zoltan 
---
 target/ppc/mmu-hash32.c |  2 +-
 target/ppc/mmu-hash32.h | 35 +--
 target/ppc/mmu_common.c |  2 +-
 3 files changed, 15 insertions(+), 24 deletions(-)

diff --git a/target/ppc/mmu-hash32.c b/target/ppc/mmu-hash32.c
index d5f2057eb1..8a446c8a7d 100644
--- a/target/ppc/mmu-hash32.c
+++ b/target/ppc/mmu-hash32.c
@@ -45,7 +45,7 @@ static int ppc_hash32_pte_prot(int mmu_idx,
 key = !!(mmuidx_pr(mmu_idx) ? (sr & SR32_KP) : (sr & SR32_KS));
 pp = pte.pte1 & HPTE32_R_PP;
 
-return ppc_hash32_pp_prot(key, pp, !!(sr & SR32_NX));
+return ppc_hash32_prot(key, pp, !!(sr & SR32_NX));
 }
 
 static target_ulong hash32_bat_size(int mmu_idx,
diff --git a/target/ppc/mmu-hash32.h b/target/ppc/mmu-hash32.h
index f0ce6951b4..bc4eedbecc 100644
--- a/target/ppc/mmu-hash32.h
+++ b/target/ppc/mmu-hash32.h
@@ -102,49 +102,40 @@ 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)
+static inline int ppc_hash32_prot(bool key, int pp, bool nx)
 {
 int prot;
 
-if (key == 0) {
+if (key) {
 switch (pp) {
 case 0x0:
-case 0x1:
-case 0x2:
-prot = PAGE_READ | PAGE_WRITE;
+prot = 0;
 break;
-
+case 0x1:
 case 0x3:
 prot = PAGE_READ;
 break;
-
+case 0x2:
+prot = PAGE_READ | PAGE_WRITE;
+break;
 default:
-abort();
+g_assert_not_reached();
 }
 } else {
 switch (pp) {
 case 0x0:
-prot = 0;
-break;
-
 case 0x1:
-case 0x3:
-prot = PAGE_READ;
-break;
-
 case 0x2:
 prot = PAGE_READ | PAGE_WRITE;
 break;
-
+case 0x3:
+prot = PAGE_READ;
+break;
 default:
-abort();
+g_assert_not_reached();
 }
 }
-if (nx == 0) {
-prot |= PAGE_EXEC;
-}
-
-return prot;
+return nx ? prot : prot | PAGE_EXEC;
 }
 
 typedef struct {
diff --git a/target/ppc/mmu_common.c b/target/ppc/mmu_common.c
index e2542694f0..08c5b61f76 100644
--- a/target/ppc/mmu_common.c
+++ b/target/ppc/mmu_common.c
@@ -120,7 +120,7 @@ static int ppc6xx_tlb_pte_check(mmu_ctx_t *ctx, 
target_ulong pte0,
 }
 /* Keep the matching PTE information */
 ctx->raddr = pte1;
-ctx->prot = ppc_hash32_pp_prot(ctx->key, pp, ctx->nx);
+ctx->prot = ppc_hash32_prot(ctx->key, pp, ctx->nx);
 if (check_prot_access_type(ctx->prot, access_type)) {
 /* Access granted */
 qemu_log_mask(CPU_LOG_MMU, "PTE access granted !\n");
-- 
2.30.9




[PATCH 40/43] target/ppc: Change parameter type of ppc64_v3_radix()

2024-05-26 Thread BALATON Zoltan
This function takes PowerPCCPU but only needs the env from it. Change
its parameter to CPUPPCState *env.

Signed-off-by: BALATON Zoltan 
---
 hw/ppc/spapr_rtas.c| 2 +-
 target/ppc/mmu-book3s-v3.h | 4 ++--
 target/ppc/mmu_common.c| 4 ++--
 3 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/hw/ppc/spapr_rtas.c b/hw/ppc/spapr_rtas.c
index f329693c55..38e94fc0d7 100644
--- a/hw/ppc/spapr_rtas.c
+++ b/hw/ppc/spapr_rtas.c
@@ -177,7 +177,7 @@ static void rtas_start_cpu(PowerPCCPU *callcpu, 
SpaprMachineState *spapr,
  * New cpus are expected to start in the same radix/hash mode
  * as the existing CPUs
  */
-if (ppc64_v3_radix(callcpu)) {
+if (ppc64_v3_radix(>env)) {
 lpcr |= LPCR_UPRT | LPCR_GTSE | LPCR_HR;
 } else {
 lpcr &= ~(LPCR_UPRT | LPCR_GTSE | LPCR_HR);
diff --git a/target/ppc/mmu-book3s-v3.h b/target/ppc/mmu-book3s-v3.h
index be66e26604..e52129ff7f 100644
--- a/target/ppc/mmu-book3s-v3.h
+++ b/target/ppc/mmu-book3s-v3.h
@@ -75,9 +75,9 @@ bool ppc64_v3_get_pate(PowerPCCPU *cpu, target_ulong lpid,
  * dig out the partition table in the fast path. This is
  * also how the HW uses it.
  */
-static inline bool ppc64_v3_radix(PowerPCCPU *cpu)
+static inline bool ppc64_v3_radix(CPUPPCState *env)
 {
-return !!(cpu->env.spr[SPR_LPCR] & LPCR_HR);
+return !!(env->spr[SPR_LPCR] & LPCR_HR);
 }
 
 #endif /* TARGET_PPC64 */
diff --git a/target/ppc/mmu_common.c b/target/ppc/mmu_common.c
index b45eb64f6e..ab055ca96b 100644
--- a/target/ppc/mmu_common.c
+++ b/target/ppc/mmu_common.c
@@ -565,7 +565,7 @@ void dump_mmu(CPUPPCState *env)
 dump_slb(env_archcpu(env));
 break;
 case POWERPC_MMU_3_00:
-if (ppc64_v3_radix(env_archcpu(env))) {
+if (ppc64_v3_radix(env)) {
 qemu_log_mask(LOG_UNIMP, "%s: the PPC64 MMU is unsupported\n",
   __func__);
 } else {
@@ -810,7 +810,7 @@ bool ppc_xlate(PowerPCCPU *cpu, vaddr eaddr, MMUAccessType 
access_type,
 switch (cpu->env.mmu_model) {
 #if defined(TARGET_PPC64)
 case POWERPC_MMU_3_00:
-if (ppc64_v3_radix(cpu)) {
+if (ppc64_v3_radix(>env)) {
 return ppc_radix64_xlate(cpu, eaddr, access_type, raddrp,
  psizep, protp, mmu_idx, guest_visible);
 }
-- 
2.30.9




[PATCH 24/43] target/ppc/mmu_common.c: Use defines instead of numeric constants

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

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

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




[PATCH 23/43] target/ppc/mmu_common.c: Rename function parameter

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

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

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




[PATCH 35/43] target/ppc/mmu-hash32.c: Change parameter type of ppc_hash32_bat_lookup()

2024-05-26 Thread BALATON Zoltan
This function takes PowerPCCPU but only needs the env from it. Change
its parameter to CPUPPCState *env.

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

diff --git a/target/ppc/mmu-hash32.c b/target/ppc/mmu-hash32.c
index 44b16142ab..a2c0ac05d2 100644
--- a/target/ppc/mmu-hash32.c
+++ b/target/ppc/mmu-hash32.c
@@ -48,11 +48,10 @@ static target_ulong hash32_bat_size(int mmu_idx,
 return BATU32_BEPI & ~((batu & BATU32_BL) << 15);
 }
 
-static hwaddr ppc_hash32_bat_lookup(PowerPCCPU *cpu, target_ulong ea,
+static hwaddr ppc_hash32_bat_lookup(CPUPPCState *env, target_ulong ea,
 MMUAccessType access_type, int *prot,
 int mmu_idx)
 {
-CPUPPCState *env = >env;
 target_ulong *BATlt, *BATut;
 bool ifetch = access_type == MMU_INST_FETCH;
 int i;
@@ -316,7 +315,7 @@ bool ppc_hash32_xlate(PowerPCCPU *cpu, vaddr eaddr, 
MMUAccessType access_type,
 
 /* 2. Check Block Address Translation entries (BATs) */
 if (env->nb_BATs != 0) {
-raddr = ppc_hash32_bat_lookup(cpu, eaddr, access_type, protp, mmu_idx);
+raddr = ppc_hash32_bat_lookup(env, eaddr, access_type, protp, mmu_idx);
 if (raddr != -1) {
 if (!check_prot_access_type(*protp, access_type)) {
 if (guest_visible) {
-- 
2.30.9




[PATCH 20/43] target/ppc/mmu_common.c: Init variable in function that relies on it

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

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

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




[PATCH 07/43] target/ppc/mmu_common.c: Return directly in ppc6xx_tlb_pte_check()

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

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

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




[PATCH 26/43] target/ppc/mmu_common.c: Stop using ctx in get_bat_6xx_tlb()

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

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

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




[PATCH 39/43] target/ppc: Change parameter type of some inline functions

2024-05-26 Thread BALATON Zoltan
These functions take PowerPCCPU but only need the env from it. Change
their parameter to CPUPPCState *env.

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

diff --git a/target/ppc/mmu-hash32.c b/target/ppc/mmu-hash32.c
index 6d0adf3357..f18faf0f46 100644
--- a/target/ppc/mmu-hash32.c
+++ b/target/ppc/mmu-hash32.c
@@ -244,10 +244,11 @@ static hwaddr ppc_hash32_htab_lookup(PowerPCCPU *cpu,
  target_ulong sr, target_ulong eaddr,
  ppc_hash_pte32_t *pte)
 {
+CPUPPCState *env = >env;
 hwaddr hpt_base, pteg_off, pte_addr, hash;
 uint32_t vsid, pgidx, ptem;
 
-hpt_base = ppc_hash32_hpt_base(cpu);
+hpt_base = ppc_hash32_hpt_base(env);
 vsid = sr & SR32_VSID;
 pgidx = (eaddr & ~SEGMENT_MASK_256M) >> TARGET_PAGE_BITS;
 hash = vsid ^ pgidx;
@@ -256,21 +257,21 @@ static hwaddr ppc_hash32_htab_lookup(PowerPCCPU *cpu,
 /* Page address translation */
 qemu_log_mask(CPU_LOG_MMU, "htab_base " HWADDR_FMT_plx " htab_mask "
   HWADDR_FMT_plx " hash " HWADDR_FMT_plx "\n",
-  hpt_base, ppc_hash32_hpt_mask(cpu), hash);
+  hpt_base, ppc_hash32_hpt_mask(env), hash);
 
 /* Primary PTEG lookup */
 qemu_log_mask(CPU_LOG_MMU, "0 htab=" HWADDR_FMT_plx "/" HWADDR_FMT_plx
   " vsid=%" PRIx32 " ptem=%" PRIx32 " hash=" HWADDR_FMT_plx
-  "\n", hpt_base, ppc_hash32_hpt_mask(cpu), vsid, ptem, hash);
-pteg_off = get_pteg_offset32(cpu, hash);
+  "\n", hpt_base, ppc_hash32_hpt_mask(env), vsid, ptem, hash);
+pteg_off = get_pteg_offset32(env, hash);
 pte_addr = ppc_hash32_pteg_search(cpu, hpt_base + pteg_off, 0, ptem, pte);
 if (pte_addr == -1) {
 /* Secondary PTEG lookup */
 qemu_log_mask(CPU_LOG_MMU, "1 htab=" HWADDR_FMT_plx "/" HWADDR_FMT_plx
   " vsid=%" PRIx32 " api=%" PRIx32 " hash=" HWADDR_FMT_plx
-  "\n", hpt_base, ppc_hash32_hpt_mask(cpu), vsid, ptem,
+  "\n", hpt_base, ppc_hash32_hpt_mask(env), vsid, ptem,
   ~hash);
-pteg_off = get_pteg_offset32(cpu, ~hash);
+pteg_off = get_pteg_offset32(env, ~hash);
 pte_addr = ppc_hash32_pteg_search(cpu, hpt_base + pteg_off, 1, ptem,
   pte);
 }
diff --git a/target/ppc/mmu-hash32.h b/target/ppc/mmu-hash32.h
index 4db55fb0a0..ec8d881def 100644
--- a/target/ppc/mmu-hash32.h
+++ b/target/ppc/mmu-hash32.h
@@ -59,19 +59,19 @@ bool ppc_hash32_xlate(PowerPCCPU *cpu, vaddr eaddr, 
MMUAccessType access_type,
 #define HPTE32_R_WIMG   0x0078
 #define HPTE32_R_PP 0x0003
 
-static inline hwaddr ppc_hash32_hpt_base(PowerPCCPU *cpu)
+static inline hwaddr ppc_hash32_hpt_base(CPUPPCState *env)
 {
-return cpu->env.spr[SPR_SDR1] & SDR_32_HTABORG;
+return env->spr[SPR_SDR1] & SDR_32_HTABORG;
 }
 
-static inline hwaddr ppc_hash32_hpt_mask(PowerPCCPU *cpu)
+static inline hwaddr ppc_hash32_hpt_mask(CPUPPCState *env)
 {
-return ((cpu->env.spr[SPR_SDR1] & SDR_32_HTABMASK) << 16) | 0x;
+return ((env->spr[SPR_SDR1] & SDR_32_HTABMASK) << 16) | 0x;
 }
 
-static inline hwaddr get_pteg_offset32(PowerPCCPU *cpu, hwaddr hash)
+static inline hwaddr get_pteg_offset32(CPUPPCState *env, hwaddr hash)
 {
-return (hash * HASH_PTEG_SIZE_32) & ppc_hash32_hpt_mask(cpu);
+return (hash * HASH_PTEG_SIZE_32) & ppc_hash32_hpt_mask(env);
 }
 
 static inline bool ppc_hash32_key(bool pr, target_ulong sr)
diff --git a/target/ppc/mmu_common.c b/target/ppc/mmu_common.c
index 60f8736210..b45eb64f6e 100644
--- a/target/ppc/mmu_common.c
+++ b/target/ppc/mmu_common.c
@@ -166,8 +166,8 @@ static int ppc6xx_tlb_check(CPUPPCState *env, hwaddr 
*raddr, int *prot,
 #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;
+hwaddr base = ppc_hash32_hpt_base(env);
+hwaddr len = ppc_hash32_hpt_mask(env) + 0x80;
 uint32_t a0, a1, a2, a3;
 
 qemu_log("Page table: " HWADDR_FMT_plx " len " HWADDR_FMT_plx "\n",
@@ -263,7 +263,6 @@ static int mmu6xx_get_physical_address(CPUPPCState *env, 
hwaddr *raddr,
hwaddr *hashp, bool *keyp,
MMUAccessType access_type, int type)
 {
-PowerPCCPU

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

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

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

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




[PATCH 18/43] target/ppc: Add function to get protection key for hash32 MMU

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

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

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




[PATCH 05/43] target/ppc/mmu_common.c: Remove another single use local variable

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

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

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




[PATCH 13/43] target/ppc/mmu_common.c: Convert local variable to bool

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

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

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




[PATCH 19/43] target/ppc/mmu-hash32.c: Inline and remove ppc_hash32_pte_prot()

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

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

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




[PATCH 08/43] target/ppc/mmu_common.c: Simplify ppc6xx_tlb_pte_check()

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

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

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




[PATCH 00/43] Remaining MMU clean up patches

2024-05-26 Thread BALATON Zoltan
This is the rest of the MMU clean up series the first part of which
was merged. Here are the remaining patches rebased and some more added.

Regards,
BALATON Zoltan

BALATON Zoltan (43):
  target/ppc: Reorganise and rename ppc_hash32_pp_prot()
  target/ppc/mmu_common.c: Remove local name for a constant
  target/ppc/mmu_common.c: Remove single use local variable
  target/ppc/mmu_common.c: Remove single use local variable
  target/ppc/mmu_common.c: Remove another single use local variable
  target/ppc/mmu_common.c: Remove yet another single use local variable
  target/ppc/mmu_common.c: Return directly in ppc6xx_tlb_pte_check()
  target/ppc/mmu_common.c: Simplify ppc6xx_tlb_pte_check()
  target/ppc/mmu_common.c: Remove unused field from mmu_ctx_t
  target/ppc/mmu_common.c: Remove hash field from mmu_ctx_t
  target/ppc/mmu_common.c: Remove pte_update_flags()
  target/ppc/mmu_common.c: Remove nx field from mmu_ctx_t
  target/ppc/mmu_common.c: Convert local variable to bool
  target/ppc/mmu_common.c: Remove single use local variable
  target/ppc/mmu_common.c: Simplify a switch statement
  target/ppc/mmu_common.c: Inline and remove ppc6xx_tlb_pte_check()
  target/ppc/mmu_common.c: Remove ptem field from mmu_ctx_t
  target/ppc: Add function to get protection key for hash32 MMU
  target/ppc/mmu-hash32.c: Inline and remove ppc_hash32_pte_prot()
  target/ppc/mmu_common.c: Init variable in function that relies on it
  target/ppc/mmu_common.c: Remove key field from mmu_ctx_t
  target/ppc/mmu_common.c: Stop using ctx in ppc6xx_tlb_check()
  target/ppc/mmu_common.c: Rename function parameter
  target/ppc/mmu_common.c: Use defines instead of numeric constants
  target/ppc: Remove bat_size_prot()
  target/ppc/mmu_common.c: Stop using ctx in get_bat_6xx_tlb()
  target/ppc/mmu_common.c: Remove mmu_ctx_t
  target/ppc/mmu-hash32.c: Inline and remove ppc_hash32_pte_raddr()
  target/ppc/mmu-hash32.c: Move get_pteg_offset32() to the header
  target/ppc: Unexport some functions from mmu-book3s-v3.h
  target/ppc/mmu-radix64: Remove externally unused parts from header
  target/ppc: Remove includes from mmu-book3s-v3.h
  target/ppc: Remove single use static inline function
  target/ppc/internal.h: Consolidate ifndef CONFIG_USER_ONLY blocks
  target/ppc/mmu-hash32.c: Change parameter type of
ppc_hash32_bat_lookup()
  target/ppc/mmu-hash32: Remove some static inlines from header
  target/ppc/mmu-hash32.c: Return and use pte address instead of base +
offset
  target/ppc/mmu-hash32.c: Use pte address as parameter instead of
offset
  target/ppc: Change parameter type of some inline functions
  target/ppc: Change parameter type of ppc64_v3_radix()
  target/ppc: Change MMU xlate functions to take CPUState
  target/ppc/mmu-hash32.c: Change parameter type of ppc_hash32_set_[rc]
  target/ppc/mmu-hash32.c: Change parameter type of
ppc_hash32_direct_store

 hw/ppc/spapr_rtas.c |   2 +-
 hw/ppc/spapr_vhyp_mmu.c |  21 +-
 target/ppc/internal.h   |  34 +--
 target/ppc/mmu-book3s-v3.c  |   1 -
 target/ppc/mmu-book3s-v3.h  |  47 +---
 target/ppc/mmu-booke.c  |   5 +-
 target/ppc/mmu-booke.h  |   2 +-
 target/ppc/mmu-hash32.c | 165 
 target/ppc/mmu-hash32.h |  86 +++---
 target/ppc/mmu-hash64.c |  54 +++-
 target/ppc/mmu-hash64.h |   3 +-
 target/ppc/mmu-radix64.c|  57 +++-
 target/ppc/mmu-radix64.h|  55 +---
 target/ppc/mmu_common.c | 405 ++--
 target/ppc/mmu_helper.c |   9 +-
 target/ppc/translate/vsx-impl.c.inc |   6 +-
 16 files changed, 376 insertions(+), 576 deletions(-)

-- 
2.30.9




[PATCH 14/43] target/ppc/mmu_common.c: Remove single use local variable

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

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

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




[PATCH 21/43] target/ppc/mmu_common.c: Remove key field from mmu_ctx_t

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

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

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




[PATCH 06/43] target/ppc/mmu_common.c: Remove yet another single use local variable

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

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

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




[PATCH 03/43] target/ppc/mmu_common.c: Remove single use local variable

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

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

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




Re: [PATCH 6/6] target/ppc: redue code duplication across Power9/10 init code

2024-05-20 Thread BALATON Zoltan

On Mon, 20 May 2024, Harsh Prateek Bora wrote:

Power9/10 initialization code consists of a lot of logical OR of
various flag bits as supported by respective Power platform during its
initialization, most of which is duplicated and only selected bits are
added or removed as needed with each new platform support being added.
Remove the duplicate code and share using common macros.

Signed-off-by: Harsh Prateek Bora 
---
target/ppc/cpu_init.h |  79 +++
target/ppc/cpu_init.c | 123 ++
2 files changed, 94 insertions(+), 108 deletions(-)
create mode 100644 target/ppc/cpu_init.h

diff --git a/target/ppc/cpu_init.h b/target/ppc/cpu_init.h
new file mode 100644
index 00..29358bfdf6
--- /dev/null
+++ b/target/ppc/cpu_init.h
@@ -0,0 +1,79 @@
+#ifndef TARGET_PPC_CPU_INIT_H
+#define TARGET_PPC_CPU_INIT_H
+
+#define POWERPC_FAMILY_POWER9_INSNS_FLAGS   \
+PPC_INSNS_BASE | PPC_ISEL | PPC_STRING | PPC_MFTB | \
+PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |   \
+PPC_FLOAT_FSQRT | PPC_FLOAT_FRSQRTE | PPC_FLOAT_FRSQRTES |  \
+PPC_FLOAT_STFIWX | PPC_FLOAT_EXT |PPC_CACHE | PPC_CACHE_ICBI |  \
+PPC_CACHE_DCBZ | PPC_MEM_SYNC | PPC_MEM_EIEIO | PPC_MEM_TLBIE | \
+PPC_MEM_TLBSYNC | PPC_64B | PPC_64H | PPC_64BX | PPC_ALTIVEC |  \
+PPC_SEGMENT_64B | PPC_SLBI | PPC_POPCNTB | PPC_POPCNTWD |   \
+PPC_CILDST
+#define POWERPC_FAMILY_POWER10_INSNS_FLAGS \
+POWERPC_FAMILY_POWER9_INSNS_FLAGS


It's a good idea to make the cpu inits more readable but I'm not sure 
about having two names for the same thing. If these are the same could 
POWER10 also just use POWERPC_FAMILY_POWER9_INSNS_FLAGS (or if you really 
want to may call it POWERPC_FAMILY_POWER9_10_INSNS_FLAGS or similar but I 
think using earlier features where unchanged in newer CPU models would be 
OK and show these are the same).


Regards,
BALATON Zoltan


+
+#define POWERPC_FAMILY_POWER9_INSNS_FLAGS2_COMMON   \
+PPC2_VSX | PPC2_VSX207 | PPC2_DFP | PPC2_DBRX | \
+PPC2_PERM_ISA206 | PPC2_DIVE_ISA206 | PPC2_ATOMIC_ISA206 |  \
+PPC2_FP_CVT_ISA206 | PPC2_FP_TST_ISA206 | PPC2_BCTAR_ISA207 |   \
+PPC2_LSQ_ISA207 | PPC2_ALTIVEC_207 | PPC2_ISA205 |  \
+PPC2_ISA207S | PPC2_FP_CVT_S64 | PPC2_ISA300 | PPC2_PRCNTL |\
+PPC2_MEM_LWSYNC | PPC2_BCDA_ISA206
+
+#define POWERPC_FAMILY_POWER9_INSNS_FLAGS2  \
+POWERPC_FAMILY_POWER9_INSNS_FLAGS2_COMMON | PPC2_TM
+#define POWERPC_FAMILY_POWER10_INSNS_FLAGS2 \
+POWERPC_FAMILY_POWER9_INSNS_FLAGS2_COMMON | PPC2_ISA310
+
+#define POWERPC_POWER9_COMMON_PCC_MSR_MASK \
+(1ull << MSR_SF) | \
+(1ull << MSR_HV) | \
+(1ull << MSR_VR) | \
+(1ull << MSR_VSX) |\
+(1ull << MSR_EE) | \
+(1ull << MSR_PR) | \
+(1ull << MSR_FP) | \
+(1ull << MSR_ME) | \
+(1ull << MSR_FE0) |\
+(1ull << MSR_SE) | \
+(1ull << MSR_DE) | \
+(1ull << MSR_FE1) |\
+(1ull << MSR_IR) | \
+(1ull << MSR_DR) | \
+(1ull << MSR_PMM) |\
+(1ull << MSR_RI) | \
+(1ull << MSR_LE)
+
+#define POWERPC_POWER9_PCC_MSR_MASK \
+POWERPC_POWER9_COMMON_PCC_MSR_MASK | (1ull << MSR_TM)
+#define POWERPC_POWER10_PCC_MSR_MASK \
+POWERPC_POWER9_COMMON_PCC_MSR_MASK
+#define POWERPC_POWER9_PCC_PCR_MASK \
+PCR_COMPAT_2_05 | PCR_COMPAT_2_06 | PCR_COMPAT_2_07
+#define POWERPC_POWER10_PCC_PCR_MASK \
+POWERPC_POWER9_PCC_PCR_MASK | PCR_COMPAT_3_00
+#define POWERPC_POWER9_PCC_PCR_SUPPORTED \
+PCR_COMPAT_3_00 | PCR_COMPAT_2_07 | PCR_COMPAT_2_06 | PCR_COMPAT_2_05
+#define POWERPC_POWER10_PCC_PCR_SUPPORTED \
+POWERPC_POWER9_PCC_PCR_SUPPORTED | PCR_COMPAT_3_10
+#define POWERPC_POWER9_PCC_LPCR_MASK\
+LPCR_VPM1 | LPCR_ISL | LPCR_KBV | LPCR_DPFD |   \
+(LPCR_PECE_U_MASK & LPCR_HVEE) | LPCR_ILE | LPCR_AIL |  \
+LPCR_UPRT | LPCR_EVIRT | LPCR_ONL | LPCR_HR | LPCR_LD | \
+(LPCR_PECE_L_MASK & (LPCR_PDEE|LPCR_HDEE|LPCR_EEE|LPCR_DEE|LPCR_OEE)) | \
+LPCR_MER | LPCR_GTSE | LPCR_TC | LPCR_HEIC | LPCR_LPES0 | LPCR_HVICE |  \
+LPCR_HDICE
+/* DD2 adds an extra HAIL bit */
+#define POWERPC_POWER10_PCC_LPCR_MASK \
+POWERPC_POWER9_PCC_LPCR_MASK | LPCR_HAIL
+#define POWERPC_POWER9_PCC_FLAGS_COMMON \
+POWERPC_FLAG_VRE | POWERPC_FLAG_SE | POWERPC_FLAG_BE |  \
+POWER

Re: [PATCH 5/6] target/ppc: reduce duplicate code between init_proc_POWER{9, 10}

2024-05-20 Thread BALATON Zoltan

On Mon, 20 May 2024, Harsh Prateek Bora wrote:

Historically, the registration of sprs have been inherited alongwith
every new Power arch support being added leading to a lot of code
duplication. It's time to do necessary cleanups now to avoid further
duplication with newer arch support being added.

Signed-off-by: Harsh Prateek Bora 
---
target/ppc/cpu_init.c | 43 +--
1 file changed, 9 insertions(+), 34 deletions(-)

diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c
index 6d82f24c87..636e12ba7a 100644
--- a/target/ppc/cpu_init.c
+++ b/target/ppc/cpu_init.c
@@ -6307,7 +6307,7 @@ static struct ppc_radix_page_info POWER9_radix_page_info 
= {
};
#endif /* CONFIG_USER_ONLY */

-static void init_proc_POWER9(CPUPPCState *env)
+static inline void register_power9_common_sprs(CPUPPCState *env)


QEMU conventions recommend not adding inline in C files and let the 
compiler decide about that. The inline may only be needed for functions 
defined in a header that are meant to be inlined in multiple files. So I 
think no inline is needed here. (I don't know if this is documented but I 
saw that in Richard Hendersons's reviews multiple times.)


Regards,
BALATON Zoltan


{
/* Common Registers */
init_proc_book3s_common(env);
@@ -6326,7 +6326,6 @@ static void init_proc_POWER9(CPUPPCState *env)
register_power5p_ear_sprs(env);
register_power5p_tb_sprs(env);
register_power6_common_sprs(env);
-register_HEIR32_spr(env);
register_power6_dbg_sprs(env);
register_power8_tce_address_control_sprs(env);
register_power8_ids_sprs(env);
@@ -6342,6 +6341,12 @@ static void init_proc_POWER9(CPUPPCState *env)
register_power9_book4_sprs(env);
register_power8_rpr_sprs(env);
register_power9_mmu_sprs(env);
+}
+
+static void init_proc_POWER9(CPUPPCState *env)
+{
+register_power9_common_sprs(env);
+register_HEIR32_spr(env);

/* POWER9 Specific registers */
spr_register_kvm(env, SPR_TIDR, "TIDR", NULL, NULL,
@@ -6499,39 +6504,9 @@ static struct ppc_radix_page_info 
POWER10_radix_page_info = {

static void init_proc_POWER10(CPUPPCState *env)
{
-/* Common Registers */
-init_proc_book3s_common(env);
-register_book3s_207_dbg_sprs(env);
-
-/* Common TCG PMU */
-init_tcg_pmu_power8(env);
-
-/* POWER8 Specific Registers */
-register_book3s_ids_sprs(env);
-register_amr_sprs(env);
-register_iamr_sprs(env);
-register_book3s_purr_sprs(env);
-register_power5p_common_sprs(env);
-register_power5p_lpar_sprs(env);
-register_power5p_ear_sprs(env);
-register_power5p_tb_sprs(env);
-register_power6_common_sprs(env);
+register_power9_common_sprs(env);
register_HEIR64_spr(env);
-register_power6_dbg_sprs(env);
-register_power8_tce_address_control_sprs(env);
-register_power8_ids_sprs(env);
-register_power8_ebb_sprs(env);
-register_power8_fscr_sprs(env);
-register_power8_pmu_sup_sprs(env);
-register_power8_pmu_user_sprs(env);
-register_power8_tm_sprs(env);
-register_power8_pspb_sprs(env);
-register_power8_dpdes_sprs(env);
-register_vtb_sprs(env);
-register_power8_ic_sprs(env);
-register_power9_book4_sprs(env);
-register_power8_rpr_sprs(env);
-register_power9_mmu_sprs(env);
+
register_power10_hash_sprs(env);
register_power10_dexcr_sprs(env);
register_power10_pmu_sup_sprs(env);





Re: [PATCH 4/6] target/ppc: optimize p9 exception handling routines

2024-05-20 Thread BALATON Zoltan

On Mon, 20 May 2024, BALATON Zoltan wrote:

On Mon, 20 May 2024, Harsh Prateek Bora wrote:

Currently, p9 exception handling has multiple if-condition checks where
it does an indirect access to pending_interrupts via env. Cache the
value during entry and reuse later to avoid multiple indirect accesses.

Signed-off-by: Harsh Prateek Bora 
---
target/ppc/excp_helper.c | 39 +--
1 file changed, 21 insertions(+), 18 deletions(-)

diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c
index 0712098cf7..4f158196bb 100644
--- a/target/ppc/excp_helper.c
+++ b/target/ppc/excp_helper.c
@@ -1844,8 +1844,10 @@ static int p8_next_unmasked_interrupt(CPUPPCState 
*env)


static int p9_interrupt_powersave(CPUPPCState *env)
{
+uint32_t pending_interrupts = env->pending_interrupts;
+


LPCR also seems to be used a lot and other similar *_powersave functions only 
use pending_interrupts and LPCR so maybe you could change these functions to 
take the pending_interrupts and lpcr as parameters and pass them from the 
caller that already have it so even this dereference could be saved?


(In that case this patch may need to be split in two as well.)

Regards,
BALATON Zoltan


/* External Exception */
-if ((env->pending_interrupts & PPC_INTERRUPT_EXT) &&
+if ((pending_interrupts & PPC_INTERRUPT_EXT) &&
(env->spr[SPR_LPCR] & LPCR_EEE)) {
bool heic = !!(env->spr[SPR_LPCR] & LPCR_HEIC);
if (!heic || !FIELD_EX64_HV(env->msr) ||
@@ -1854,35 +1856,35 @@ static int p9_interrupt_powersave(CPUPPCState *env)
}
}
/* Decrementer Exception */
-if ((env->pending_interrupts & PPC_INTERRUPT_DECR) &&
+if ((pending_interrupts & PPC_INTERRUPT_DECR) &&
(env->spr[SPR_LPCR] & LPCR_DEE)) {
return PPC_INTERRUPT_DECR;
}
/* Machine Check or Hypervisor Maintenance Exception */
if (env->spr[SPR_LPCR] & LPCR_OEE) {
-if (env->pending_interrupts & PPC_INTERRUPT_MCK) {
+if (pending_interrupts & PPC_INTERRUPT_MCK) {
return PPC_INTERRUPT_MCK;
}
-if (env->pending_interrupts & PPC_INTERRUPT_HMI) {
+if (pending_interrupts & PPC_INTERRUPT_HMI) {
return PPC_INTERRUPT_HMI;
}
}
/* Privileged Doorbell Exception */
-if ((env->pending_interrupts & PPC_INTERRUPT_DOORBELL) &&
+if ((pending_interrupts & PPC_INTERRUPT_DOORBELL) &&
(env->spr[SPR_LPCR] & LPCR_PDEE)) {
return PPC_INTERRUPT_DOORBELL;
}
/* Hypervisor Doorbell Exception */
-if ((env->pending_interrupts & PPC_INTERRUPT_HDOORBELL) &&
+if ((pending_interrupts & PPC_INTERRUPT_HDOORBELL) &&
(env->spr[SPR_LPCR] & LPCR_HDEE)) {
return PPC_INTERRUPT_HDOORBELL;
}
/* Hypervisor virtualization exception */
-if ((env->pending_interrupts & PPC_INTERRUPT_HVIRT) &&
+if ((pending_interrupts & PPC_INTERRUPT_HVIRT) &&
(env->spr[SPR_LPCR] & LPCR_HVEE)) {
return PPC_INTERRUPT_HVIRT;
}
-if (env->pending_interrupts & PPC_INTERRUPT_RESET) {
+if (pending_interrupts & PPC_INTERRUPT_RESET) {
return PPC_INTERRUPT_RESET;
}
return 0;
@@ -1891,11 +1893,12 @@ static int p9_interrupt_powersave(CPUPPCState *env)
static int p9_next_unmasked_interrupt(CPUPPCState *env)
{
CPUState *cs = env_cpu(env);
+uint32_t pending_interrupts = env->pending_interrupts;

/* Ignore MSR[EE] when coming out of some power management states */
bool msr_ee = FIELD_EX64(env->msr, MSR, EE) || env->resume_as_sreset;

-assert((env->pending_interrupts & P9_UNUSED_INTERRUPTS) == 0);
+assert((pending_interrupts & P9_UNUSED_INTERRUPTS) == 0);

if (cs->halted) {
if (env->spr[SPR_PSSCR] & PSSCR_EC) {
@@ -1914,12 +1917,12 @@ static int p9_next_unmasked_interrupt(CPUPPCState 
*env)

}

/* Machine check exception */
-if (env->pending_interrupts & PPC_INTERRUPT_MCK) {
+if (pending_interrupts & PPC_INTERRUPT_MCK) {
return PPC_INTERRUPT_MCK;
}

/* Hypervisor decrementer exception */
-if (env->pending_interrupts & PPC_INTERRUPT_HDECR) {
+if (pending_interrupts & PPC_INTERRUPT_HDECR) {
/* LPCR will be clear when not supported so this will work */
bool hdice = !!(env->spr[SPR_LPCR] & LPCR_HDICE);
if ((msr_ee || !FIELD_EX64_HV(env->msr)) && hdice) {
@@ -1929,7 +1932,7 @@ static int p9_next_unmasked_interrupt(CPUPPCState 
*env)

}

/* Hypervisor virtualization interrupt */
-if (env->pending_interrupts & PPC_INTERRUPT_HVIRT) {
+if (pending_interrupts & PPC_INTERRUPT_HVIRT) {
/* LPCR will be clear when not supported so this will work */
  

Re: [PATCH 4/6] target/ppc: optimize p9 exception handling routines

2024-05-20 Thread BALATON Zoltan

On Mon, 20 May 2024, Harsh Prateek Bora wrote:

Currently, p9 exception handling has multiple if-condition checks where
it does an indirect access to pending_interrupts via env. Cache the
value during entry and reuse later to avoid multiple indirect accesses.

Signed-off-by: Harsh Prateek Bora 
---
target/ppc/excp_helper.c | 39 +--
1 file changed, 21 insertions(+), 18 deletions(-)

diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c
index 0712098cf7..4f158196bb 100644
--- a/target/ppc/excp_helper.c
+++ b/target/ppc/excp_helper.c
@@ -1844,8 +1844,10 @@ static int p8_next_unmasked_interrupt(CPUPPCState *env)

static int p9_interrupt_powersave(CPUPPCState *env)
{
+uint32_t pending_interrupts = env->pending_interrupts;
+


LPCR also seems to be used a lot and other similar *_powersave functions 
only use pending_interrupts and LPCR so maybe you could change these 
functions to take the pending_interrupts and lpcr as parameters and pass 
them from the caller that already have it so even this dereference could 
be saved?


Regards,
BALATON Zoltan


/* External Exception */
-if ((env->pending_interrupts & PPC_INTERRUPT_EXT) &&
+if ((pending_interrupts & PPC_INTERRUPT_EXT) &&
(env->spr[SPR_LPCR] & LPCR_EEE)) {
bool heic = !!(env->spr[SPR_LPCR] & LPCR_HEIC);
if (!heic || !FIELD_EX64_HV(env->msr) ||
@@ -1854,35 +1856,35 @@ static int p9_interrupt_powersave(CPUPPCState *env)
}
}
/* Decrementer Exception */
-if ((env->pending_interrupts & PPC_INTERRUPT_DECR) &&
+if ((pending_interrupts & PPC_INTERRUPT_DECR) &&
(env->spr[SPR_LPCR] & LPCR_DEE)) {
return PPC_INTERRUPT_DECR;
}
/* Machine Check or Hypervisor Maintenance Exception */
if (env->spr[SPR_LPCR] & LPCR_OEE) {
-if (env->pending_interrupts & PPC_INTERRUPT_MCK) {
+if (pending_interrupts & PPC_INTERRUPT_MCK) {
return PPC_INTERRUPT_MCK;
}
-if (env->pending_interrupts & PPC_INTERRUPT_HMI) {
+if (pending_interrupts & PPC_INTERRUPT_HMI) {
return PPC_INTERRUPT_HMI;
}
}
/* Privileged Doorbell Exception */
-if ((env->pending_interrupts & PPC_INTERRUPT_DOORBELL) &&
+if ((pending_interrupts & PPC_INTERRUPT_DOORBELL) &&
(env->spr[SPR_LPCR] & LPCR_PDEE)) {
return PPC_INTERRUPT_DOORBELL;
}
/* Hypervisor Doorbell Exception */
-if ((env->pending_interrupts & PPC_INTERRUPT_HDOORBELL) &&
+if ((pending_interrupts & PPC_INTERRUPT_HDOORBELL) &&
(env->spr[SPR_LPCR] & LPCR_HDEE)) {
return PPC_INTERRUPT_HDOORBELL;
}
/* Hypervisor virtualization exception */
-if ((env->pending_interrupts & PPC_INTERRUPT_HVIRT) &&
+if ((pending_interrupts & PPC_INTERRUPT_HVIRT) &&
(env->spr[SPR_LPCR] & LPCR_HVEE)) {
return PPC_INTERRUPT_HVIRT;
}
-if (env->pending_interrupts & PPC_INTERRUPT_RESET) {
+if (pending_interrupts & PPC_INTERRUPT_RESET) {
return PPC_INTERRUPT_RESET;
}
return 0;
@@ -1891,11 +1893,12 @@ static int p9_interrupt_powersave(CPUPPCState *env)
static int p9_next_unmasked_interrupt(CPUPPCState *env)
{
CPUState *cs = env_cpu(env);
+uint32_t pending_interrupts = env->pending_interrupts;

/* Ignore MSR[EE] when coming out of some power management states */
bool msr_ee = FIELD_EX64(env->msr, MSR, EE) || env->resume_as_sreset;

-assert((env->pending_interrupts & P9_UNUSED_INTERRUPTS) == 0);
+assert((pending_interrupts & P9_UNUSED_INTERRUPTS) == 0);

if (cs->halted) {
if (env->spr[SPR_PSSCR] & PSSCR_EC) {
@@ -1914,12 +1917,12 @@ static int p9_next_unmasked_interrupt(CPUPPCState *env)
}

/* Machine check exception */
-if (env->pending_interrupts & PPC_INTERRUPT_MCK) {
+if (pending_interrupts & PPC_INTERRUPT_MCK) {
return PPC_INTERRUPT_MCK;
}

/* Hypervisor decrementer exception */
-if (env->pending_interrupts & PPC_INTERRUPT_HDECR) {
+if (pending_interrupts & PPC_INTERRUPT_HDECR) {
/* LPCR will be clear when not supported so this will work */
bool hdice = !!(env->spr[SPR_LPCR] & LPCR_HDICE);
if ((msr_ee || !FIELD_EX64_HV(env->msr)) && hdice) {
@@ -1929,7 +1932,7 @@ static int p9_next_unmasked_interrupt(CPUPPCState *env)
}

/* Hypervisor virtualization interrupt */
-if (env->pending_interrupts & PPC_INTERRUPT_HVIRT) {
+if (pending_interrupts & PPC_INTERRUPT_HVIRT) {
/* LPCR will be clear when not supported so this will work */
bool hvice = !!(env->spr[SPR_LPCR] & LPCR_HVICE);
if ((msr_ee || !FIELD_EX64_HV(env->msr)) &am

Re: [PATCH 3/6] target/ppc: optimize hreg_compute_pmu_hflags_value

2024-05-20 Thread BALATON Zoltan

On Mon, 20 May 2024, Harsh Prateek Bora wrote:

The second if-condition can be true only if the first one above is true.
Enclose the latter into the former to avoid un-necessary check if first
condition fails.

Signed-off-by: Harsh Prateek Bora 


Reviewed-by: BALATON Zoltan 


---
target/ppc/helper_regs.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/target/ppc/helper_regs.c b/target/ppc/helper_regs.c
index 5de0df5795..89aacdf212 100644
--- a/target/ppc/helper_regs.c
+++ b/target/ppc/helper_regs.c
@@ -66,9 +66,9 @@ static uint32_t hreg_compute_pmu_hflags_value(CPUPPCState 
*env)
#ifndef CONFIG_USER_ONLY
if (env->pmc_ins_cnt) {
hflags |= 1 << HFLAGS_INSN_CNT;
-}
-if (env->pmc_ins_cnt & 0x1e) {
-hflags |= 1 << HFLAGS_PMC_OTHER;
+if (env->pmc_ins_cnt & 0x1e) {
+hflags |= 1 << HFLAGS_PMC_OTHER;
+}
}
#endif
#endif





Re: [PATCH 2/6] target/ppc: optimize hreg_compute_pmu_hflags_value

2024-05-20 Thread BALATON Zoltan

On Mon, 20 May 2024, Harsh Prateek Bora wrote:

Cache env->spr[SPR_POWER_MMCR0] in a local variable as used in multiple
conditions to avoid multiple indirect accesses.

Signed-off-by: Harsh Prateek Bora 
---
target/ppc/helper_regs.c | 9 +
1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/target/ppc/helper_regs.c b/target/ppc/helper_regs.c
index 945fa1a596..5de0df5795 100644
--- a/target/ppc/helper_regs.c
+++ b/target/ppc/helper_regs.c
@@ -50,15 +50,16 @@ void hreg_swap_gpr_tgpr(CPUPPCState *env)
static uint32_t hreg_compute_pmu_hflags_value(CPUPPCState *env)
{
uint32_t hflags = 0;
-
#if defined(TARGET_PPC64)
-if (env->spr[SPR_POWER_MMCR0] & MMCR0_PMCC0) {
+target_ulong spr_power_mmcr0 = env->spr[SPR_POWER_MMCR0];


I think this is simple enough so the compiler should be able to find out 
on its own but adding a local is also simple and may make it more readable 
but I'd call it just mmcr0 for readability.


Regards,
BALATON Zoltan


+
+if (spr_power_mmcr0 & MMCR0_PMCC0) {
hflags |= 1 << HFLAGS_PMCC0;
}
-if (env->spr[SPR_POWER_MMCR0] & MMCR0_PMCC1) {
+if (spr_power_mmcr0 & MMCR0_PMCC1) {
hflags |= 1 << HFLAGS_PMCC1;
}
-if (env->spr[SPR_POWER_MMCR0] & MMCR0_PMCjCE) {
+if (spr_power_mmcr0 & MMCR0_PMCjCE) {
hflags |= 1 << HFLAGS_PMCJCE;
}






[PATCH] macio: Add unimp region for debugging

2024-05-20 Thread BALATON Zoltan
The macio device has a container mmio region that embeds several other
devices. Some of these devices are not implemented but because of the
container region, the unassigned memory traces don't catch accesses to
these. To help debugging, add an unimplemented-device covering the
container region to get logs when the guest accesses unassigned areas.

Signed-off-by: BALATON Zoltan 
---
Here's a patch that should help getting logs for unimplemented registers
in macio with -d unimp which may help finding out where the writes go and
what needs to be implemented.

 hw/misc/Kconfig   | 1 +
 hw/misc/macio/macio.c | 9 +
 2 files changed, 10 insertions(+)

diff --git a/hw/misc/Kconfig b/hw/misc/Kconfig
index 1e08785b83..4197a786d6 100644
--- a/hw/misc/Kconfig
+++ b/hw/misc/Kconfig
@@ -66,6 +66,7 @@ config MACIO
 select MAC_DBDMA
 select MAC_NVRAM
 select MOS6522
+select UNIMP
 
 config IVSHMEM_DEVICE
 bool
diff --git a/hw/misc/macio/macio.c b/hw/misc/macio/macio.c
index 3f449f91c0..43b683c294 100644
--- a/hw/misc/macio/macio.c
+++ b/hw/misc/macio/macio.c
@@ -34,6 +34,7 @@
 #include "hw/char/escc.h"
 #include "hw/misc/macio/macio.h"
 #include "hw/intc/heathrow_pic.h"
+#include "hw/misc/unimp.h"
 #include "trace.h"
 
 #define ESCC_CLOCK 3686400
@@ -94,6 +95,14 @@ static bool macio_common_realize(PCIDevice *d, Error **errp)
 {
 MacIOState *s = MACIO(d);
 SysBusDevice *sbd;
+DeviceState *dev = qdev_new(TYPE_UNIMPLEMENTED_DEVICE);
+
+qdev_prop_set_string(dev, "name", "macio-unimp");
+qdev_prop_set_uint64(dev, "size", memory_region_size(>bar));
+sbd = SYS_BUS_DEVICE(dev);
+sysbus_realize_and_unref(sbd, _fatal);
+memory_region_add_subregion_overlap(>bar, 0,
+sysbus_mmio_get_region(sbd, 0), -1000);
 
 if (!qdev_realize(DEVICE(>dbdma), BUS(>macio_bus), errp)) {
 return false;
-- 
2.30.9




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

2024-05-18 Thread BALATON Zoltan

On Fri, 17 May 2024, Nicholas Piggin wrote:

On Mon May 13, 2024 at 9:28 AM AEST, BALATON Zoltan wrote:

This is used only once and can be inlined.


This reminds me, ppc_hash32_pp_prot() calculates prot from
pp and nx (which is not from pp but from segment) and from
key of course. It could be renamed to say ppc_hash32_prot().
Maybe do that when you split out the rearranging of that
function.


OK, I can rename it again. This is what you said before:
https://lists.nongnu.org/archive/html/qemu-ppc/2024-05/msg00120.html
that's why it was kept as it is but I'll drop the pp form the name.

Regards,
BALATON Zoltan


Thanks,
Nick



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

diff --git a/target/ppc/mmu-hash32.c b/target/ppc/mmu-hash32.c
index 8e5e83f46a..9de42713b3 100644
--- a/target/ppc/mmu-hash32.c
+++ b/target/ppc/mmu-hash32.c
@@ -37,17 +37,6 @@
 #  define LOG_BATS(...) do { } while (0)
 #endif

-static int ppc_hash32_pte_prot(int mmu_idx,
-   target_ulong sr, ppc_hash_pte32_t pte)
-{
-unsigned pp, key;
-
-key = ppc_hash32_key(mmuidx_pr(mmu_idx), sr);
-pp = pte.pte1 & HPTE32_R_PP;
-
-return ppc_hash32_pp_prot(key, pp, !!(sr & SR32_NX));
-}
-
 static target_ulong hash32_bat_size(int mmu_idx,
 target_ulong batu, target_ulong batl)
 {
@@ -341,10 +330,10 @@ bool ppc_hash32_xlate(PowerPCCPU *cpu, vaddr eaddr, 
MMUAccessType access_type,
 CPUState *cs = CPU(cpu);
 CPUPPCState *env = >env;
 target_ulong sr;
-hwaddr pte_offset;
+hwaddr pte_offset, raddr;
 ppc_hash_pte32_t pte;
+bool key;
 int prot;
-hwaddr raddr;

 /* There are no hash32 large pages. */
 *psizep = TARGET_PAGE_BITS;
@@ -426,8 +415,8 @@ bool ppc_hash32_xlate(PowerPCCPU *cpu, vaddr eaddr, 
MMUAccessType access_type,
 "found PTE at offset %08" HWADDR_PRIx "\n", pte_offset);

 /* 7. Check access permissions */
-
-prot = ppc_hash32_pte_prot(mmu_idx, sr, pte);
+key = ppc_hash32_key(mmuidx_pr(mmu_idx), sr);
+prot = ppc_hash32_pp_prot(key, pte.pte1 & HPTE32_R_PP, sr & SR32_NX);

 if (!check_prot_access_type(prot, access_type)) {
 /* Access right violation */








Re: [PATCH 02/14] target/ppc: Remove redundant MEMOP_GET_SIZE macro

2024-05-18 Thread BALATON Zoltan

On Sat, 18 May 2024, Nicholas Piggin wrote:

There is a memop_size() function for this.

Signed-off-by: Nicholas Piggin 


Reviewed-by: BALATON Zoltan 


---
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 0882fe2fd2..cf2404330b 100644
--- a/target/ppc/translate.c
+++ b/target/ppc/translate.c
@@ -2904,8 +2904,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)];
@@ -2938,7 +2936,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);

@@ -2948,7 +2946,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);
}

@@ -3110,7 +3108,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);





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

2024-05-18 Thread BALATON Zoltan

On Sat, 18 May 2024, Nicholas Piggin wrote:

On Mon May 13, 2024 at 9:27 AM AEST, BALATON Zoltan wrote:

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


FYI I put patch 35 (only taking half of 35) and minus patch 28
here, will merge after some more testing. (Don't rebase your
series on this because it's just a throwaway branch).

https://gitlab.com/npiggin/qemu/-/commits/ppc-next-test


OK thanks, I'll wait for the pull and then rebase on that then.

Regards,
BALATON Zoltan



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

2024-05-17 Thread BALATON Zoltan

On Fri, 17 May 2024, Nicholas Piggin wrote:

On Mon May 13, 2024 at 9:28 AM AEST, BALATON Zoltan wrote:

The mmask local variable is a less descriptive local name for a
constant. Drop it and use the constant directly in the two places it
is needed.


Wow, lots more. I might take up to patch 34ish for first PR.


Yes I think that might be a good idea, just what I said in previous reply, 
as I have some more already even compared to this version. There's a lot 
to clean up in this series and I did not even attempt to fix the 6xx cases 
that I won't do because I don't know it so just tried to separate these 
and do some trivial clean up/improvement.


Regards,
BALATON Zoltan


Thanks,
Nick



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

diff --git a/target/ppc/mmu_common.c b/target/ppc/mmu_common.c
index 9e0bfbda67..5d0090014a 100644
--- a/target/ppc/mmu_common.c
+++ b/target/ppc/mmu_common.c
@@ -98,7 +98,7 @@ static int ppc6xx_tlb_pte_check(mmu_ctx_t *ctx, target_ulong 
pte0,
 target_ulong pte1, int h,
 MMUAccessType access_type)
 {
-target_ulong ptem, mmask;
+target_ulong ptem;
 int ret, pteh, ptev, pp;

 ret = -1;
@@ -108,12 +108,11 @@ static int ppc6xx_tlb_pte_check(mmu_ctx_t *ctx, 
target_ulong pte0,
 if (ptev && h == pteh) {
 /* Check vsid & api */
 ptem = pte0 & PTE_PTEM_MASK;
-mmask = PTE_CHECK_MASK;
 pp = pte1 & 0x0003;
 if (ptem == ctx->ptem) {
 if (ctx->raddr != (hwaddr)-1ULL) {
 /* all matches should have equal RPN, WIMG & PP */
-if ((ctx->raddr & mmask) != (pte1 & mmask)) {
+if ((ctx->raddr & PTE_CHECK_MASK) != (pte1 & PTE_CHECK_MASK)) {
 qemu_log_mask(CPU_LOG_MMU, "Bad RPN/WIMG/PP\n");
 return -3;
 }








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

2024-05-17 Thread BALATON Zoltan

On Fri, 17 May 2024, Nicholas Piggin wrote:

On Mon May 13, 2024 at 9:28 AM AEST, BALATON Zoltan wrote:

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.



It's already hard to review patches that move code around, it's better
to keep the changes before/after the move unless really necessary.


I could try to split this further but the series was already quite long 
and this is not too complex and also there's git diff --color-moved so I 
though this could be in in one patch.



For mmu_common.c hunks,

Reviewed-by: Nicholas Piggin 


Hmm, I can't apply Rb to hunks so I think I have to ignore it for now and 
wait until you send Rb for whole patch.


Just to make it simpler could you please send a pull request for the 
patches that are already reviewed at the beginning of the series to reduce 
the number of patches I need to resend? I've already added some more and 
still have some plans to continue so moving the patches that are OK out of 
the way could help. Then I could just resend the patches starting from the 
first that's not yet reviewed. Thank you for taking time to review these.


Regards,
BALATON Zoltan


Thanks,
Nick


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

diff --git a/target/ppc/mmu-hash32.c b/target/ppc/mmu-hash32.c
index 1e8f1df0f0..d5f2057eb1 100644
--- a/target/ppc/mmu-hash32.c
+++ b/target/ppc/mmu-hash32.c
@@ -37,51 +37,6 @@
 #  define LOG_BATS(...) do { } while (0)
 #endif

-static int ppc_hash32_pp_prot(int key, int pp, int nx)
-{
-int prot;
-
-if (key == 0) {
-switch (pp) {
-case 0x0:
-case 0x1:
-case 0x2:
-prot = PAGE_READ | PAGE_WRITE;
-break;
-
-case 0x3:
-prot = PAGE_READ;
-break;
-
-default:
-abort();
-}
-} else {
-switch (pp) {
-case 0x0:
-prot = 0;
-break;
-
-case 0x1:
-case 0x3:
-prot = PAGE_READ;
-break;
-
-case 0x2:
-prot = PAGE_READ | PAGE_WRITE;
-break;
-
-default:
-abort();
-}
-}
-if (nx == 0) {
-prot |= PAGE_EXEC;
-}
-
-return prot;
-}
-
 static int ppc_hash32_pte_prot(int mmu_idx,
target_ulong sr, ppc_hash_pte32_t pte)
 {
diff --git a/target/ppc/mmu-hash32.h b/target/ppc/mmu-hash32.h
index 7119a63d97..bf99161858 100644
--- a/target/ppc/mmu-hash32.h
+++ b/target/ppc/mmu-hash32.h
@@ -102,6 +102,42 @@ static inline void ppc_hash32_store_hpte1(PowerPCCPU *cpu,
 stl_phys(CPU(cpu)->as, base + pte_offset + HASH_PTE_SIZE_32 / 2, pte1);
 }

+static inline int ppc_hash32_pp_prot(bool key, int pp, bool nx)
+{
+int prot;
+
+if (key) {
+switch (pp) {
+case 0x0:
+prot = 0;
+break;
+case 0x1:
+case 0x3:
+prot = PAGE_READ;
+break;
+case 0x2:
+prot = PAGE_READ | PAGE_WRITE;
+break;
+default:
+g_assert_not_reached();
+}
+} else {
+switch (pp) {
+case 0x0:
+case 0x1:
+case 0x2:
+prot = PAGE_READ | PAGE_WRITE;
+break;
+case 0x3:
+prot = PAGE_READ;
+break;
+default:
+g_assert_not_reached();
+}
+}
+return nx ? prot : prot | PAGE_EXEC;
+}
+
 typedef struct {
 uint32_t pte0, pte1;
 } ppc_hash_pte32_t;
diff --git a/target/ppc/mmu_common.c b/target/ppc/mmu_common.c
index e1462a25dd..9e0bfbda67 100644
--- a/target/ppc/mmu_common.c
+++ b/target/ppc/mmu_common.c
@@ -77,44 +77,6 @@ void ppc_store_sdr1(CPUPPCState *env, target_ulong value)
 /*/
 /* PowerPC MMU emulation */

-static int pp_check(int key, int pp, int nx)
-{
-int access;
-
-/* Compute access rights */
-access = 0;
-if (key == 0) {
-switch (pp) {
-case 0x0:
-case 0x1:
-case 0x2:
-access |= PAGE_WRITE;
-/* fall through */
-case 0x3:
-access |= PAGE_READ;
-break;
-}
-} else {
-switch (pp) {
-case 0x0:
-access = 0;
-break;
-case 0x1:
-case 0x3:
-access = PAGE_READ;
-break;
-case 0x2:
-access = PAGE_READ | PAGE_WRITE;
-br

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

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

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

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




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

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

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

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




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

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

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

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

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

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

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

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




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

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

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

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




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

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

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

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




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

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

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

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




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

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

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

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




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

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

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

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

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

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

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

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




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

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

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

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




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

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

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

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




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

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

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

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




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

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

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

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

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

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

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

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




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

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

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

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




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

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

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

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




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

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

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

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

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

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

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

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




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

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

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

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




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

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

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

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




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

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

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

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




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

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

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

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




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

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

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

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




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

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

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

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




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

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

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

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




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

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

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

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




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

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

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

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




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

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

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

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




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

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

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

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




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

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

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

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




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

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

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

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




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

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

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

diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h
index cfb3ba5ac8..92b50a1be2 100644
--- a/target/ppc/cpu.h
+++ b/target/ppc/cpu.h
@@ -1606,10 +1606,6 @@ void ppc_tlb_invalidate_all(CPUPPCState *env);
 void ppc_tlb_invalidate_one(CPUPPCState *env, target_ulong addr);
 void cpu_ppc_set_vhyp(PowerPCCPU *cpu, PPCVirtualHypervisor *vhyp);
 void cpu_ppc_set_1lpar(PowerPCCPU *cpu);
-int ppcmas_tlb_check(CPUPPCState *env, ppcmas_tlb_t *tlb, hwaddr *raddrp,
- target_ulong address, uint32_t pid);
-int ppcemb_tlb_search(CPUPPCState *env, target_ulong address, uint32_t pid);
-hwaddr booke206_tlb_to_page_size(CPUPPCState *env, ppcmas_tlb_t *tlb);
 #endif
 
 void ppc_store_fpscr(CPUPPCState *env, target_ulong val);
diff --git a/target/ppc/meson.build b/target/ppc/meson.build
index 0b89f9b89f..db3b7a0c33 100644
--- a/target/ppc/meson.build
+++ b/target/ppc/meson.build
@@ -37,6 +37,7 @@ ppc_system_ss.add(files(
   'arch_dump.c',
   'machine.c',
   'mmu-hash32.c',
+  'mmu-booke.c',
   'mmu_common.c',
   'ppc-qmp-cmds.c',
 ))
diff --git a/target/ppc/mmu-booke.c b/target/ppc/mmu-booke.c
new file mode 100644
index 00..55e5dd7c6b
--- /dev/null
+++ b/target/ppc/mmu-booke.c
@@ -0,0 +1,531 @@
+/*
+ *  PowerPC BookE MMU, TLB emulation helpers for QEMU.
+ *
+ *  Copyright (c) 2003-2007 Jocelyn Mayer
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <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;
+qemu_log_mask(CPU_LOG_MMU,
+  "%s: TLB

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

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

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

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

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

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

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

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




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

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

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

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




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

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

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

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




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

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

v7:
- Added more clean ups

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

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

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

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

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

Regards,
BALATON Zoltan


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

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

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

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

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

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




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

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

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

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




  1   2   3   4   5   6   7   8   9   10   >