2016-06-29 14:47:03 +03:00
|
|
|
#ifndef MMU_HASH32_H
|
|
|
|
#define MMU_HASH32_H
|
2013-03-12 04:31:07 +04:00
|
|
|
|
|
|
|
#ifndef CONFIG_USER_ONLY
|
|
|
|
|
2021-06-21 15:51:13 +03:00
|
|
|
bool ppc_hash32_xlate(PowerPCCPU *cpu, vaddr eaddr, MMUAccessType access_type,
|
2021-07-06 18:03:16 +03:00
|
|
|
hwaddr *raddrp, int *psizep, int *protp, int mmu_idx,
|
2021-06-21 15:51:13 +03:00
|
|
|
bool guest_visible);
|
2013-03-12 04:31:07 +04:00
|
|
|
|
2013-03-12 04:31:18 +04:00
|
|
|
/*
|
|
|
|
* Segment register definitions
|
|
|
|
*/
|
|
|
|
|
|
|
|
#define SR32_T 0x80000000
|
|
|
|
#define SR32_KS 0x40000000
|
|
|
|
#define SR32_KP 0x20000000
|
|
|
|
#define SR32_NX 0x10000000
|
|
|
|
#define SR32_VSID 0x00ffffff
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Block Address Translation (BAT) definitions
|
|
|
|
*/
|
|
|
|
|
2021-07-03 00:52:35 +03:00
|
|
|
#define BATU32_BEPIU 0xf0000000
|
|
|
|
#define BATU32_BEPIL 0x0ffe0000
|
2013-03-12 04:31:18 +04:00
|
|
|
#define BATU32_BEPI 0xfffe0000
|
|
|
|
#define BATU32_BL 0x00001ffc
|
|
|
|
#define BATU32_VS 0x00000002
|
|
|
|
#define BATU32_VP 0x00000001
|
|
|
|
|
|
|
|
|
|
|
|
#define BATL32_BRPN 0xfffe0000
|
|
|
|
#define BATL32_WIMG 0x00000078
|
|
|
|
#define BATL32_PP 0x00000003
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Hash page table definitions
|
|
|
|
*/
|
target/ppc: Eliminate htab_base and htab_mask variables
CPUPPCState includes fields htab_base and htab_mask which store the base
address (GPA) and size (as a mask) of the guest's hashed page table (HPT).
These are set when the SDR1 register is updated.
Keeping these in sync with the SDR1 is actually a little bit fiddly, and
probably not useful for performance, since keeping them expands the size of
CPUPPCState. It also makes some upcoming changes harder to implement.
This patch removes these fields, in favour of calculating them directly
from the SDR1 contents when necessary.
This does make a change to the behaviour of attempting to write a bad value
(invalid HPT size) to the SDR1 with an mtspr instruction. Previously, the
bad value would be stored in SDR1 and could be retrieved with a later
mfspr, but the HPT size as used by the softmmu would be, clamped to the
allowed values. Now, writing a bad value is treated as a no-op. An error
message is printed in both new and old versions.
I'm not sure which behaviour, if either, matches real hardware. I don't
think it matters that much, since it's pretty clear that if an OS writes
a bad value to SDR1, it's not going to boot.
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Reviewed-by: Alexey Kardashevskiy <aik@ozlabs.ru>
2017-02-24 08:36:44 +03:00
|
|
|
#define SDR_32_HTABORG 0xFFFF0000UL
|
|
|
|
#define SDR_32_HTABMASK 0x000001FFUL
|
2013-03-12 04:31:18 +04:00
|
|
|
|
|
|
|
#define HPTES_PER_GROUP 8
|
|
|
|
#define HASH_PTE_SIZE_32 8
|
|
|
|
#define HASH_PTEG_SIZE_32 (HASH_PTE_SIZE_32 * HPTES_PER_GROUP)
|
|
|
|
|
|
|
|
#define HPTE32_V_VALID 0x80000000
|
|
|
|
#define HPTE32_V_VSID 0x7fffff80
|
|
|
|
#define HPTE32_V_SECONDARY 0x00000040
|
|
|
|
#define HPTE32_V_API 0x0000003f
|
|
|
|
#define HPTE32_V_COMPARE(x, y) (!(((x) ^ (y)) & 0x7fffffbf))
|
|
|
|
|
|
|
|
#define HPTE32_R_RPN 0xfffff000
|
|
|
|
#define HPTE32_R_R 0x00000100
|
|
|
|
#define HPTE32_R_C 0x00000080
|
|
|
|
#define HPTE32_R_W 0x00000040
|
|
|
|
#define HPTE32_R_I 0x00000020
|
|
|
|
#define HPTE32_R_M 0x00000010
|
|
|
|
#define HPTE32_R_G 0x00000008
|
|
|
|
#define HPTE32_R_WIMG 0x00000078
|
|
|
|
#define HPTE32_R_PP 0x00000003
|
|
|
|
|
target/ppc: Eliminate htab_base and htab_mask variables
CPUPPCState includes fields htab_base and htab_mask which store the base
address (GPA) and size (as a mask) of the guest's hashed page table (HPT).
These are set when the SDR1 register is updated.
Keeping these in sync with the SDR1 is actually a little bit fiddly, and
probably not useful for performance, since keeping them expands the size of
CPUPPCState. It also makes some upcoming changes harder to implement.
This patch removes these fields, in favour of calculating them directly
from the SDR1 contents when necessary.
This does make a change to the behaviour of attempting to write a bad value
(invalid HPT size) to the SDR1 with an mtspr instruction. Previously, the
bad value would be stored in SDR1 and could be retrieved with a later
mfspr, but the HPT size as used by the softmmu would be, clamped to the
allowed values. Now, writing a bad value is treated as a no-op. An error
message is printed in both new and old versions.
I'm not sure which behaviour, if either, matches real hardware. I don't
think it matters that much, since it's pretty clear that if an OS writes
a bad value to SDR1, it's not going to boot.
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Reviewed-by: Alexey Kardashevskiy <aik@ozlabs.ru>
2017-02-24 08:36:44 +03:00
|
|
|
static inline hwaddr ppc_hash32_hpt_base(PowerPCCPU *cpu)
|
|
|
|
{
|
|
|
|
return cpu->env.spr[SPR_SDR1] & SDR_32_HTABORG;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline hwaddr ppc_hash32_hpt_mask(PowerPCCPU *cpu)
|
|
|
|
{
|
|
|
|
return ((cpu->env.spr[SPR_SDR1] & SDR_32_HTABMASK) << 16) | 0xFFFF;
|
|
|
|
}
|
|
|
|
|
2016-01-14 07:33:27 +03:00
|
|
|
static inline target_ulong ppc_hash32_load_hpte0(PowerPCCPU *cpu,
|
2013-03-12 04:31:19 +04:00
|
|
|
hwaddr pte_offset)
|
|
|
|
{
|
target/ppc: Eliminate htab_base and htab_mask variables
CPUPPCState includes fields htab_base and htab_mask which store the base
address (GPA) and size (as a mask) of the guest's hashed page table (HPT).
These are set when the SDR1 register is updated.
Keeping these in sync with the SDR1 is actually a little bit fiddly, and
probably not useful for performance, since keeping them expands the size of
CPUPPCState. It also makes some upcoming changes harder to implement.
This patch removes these fields, in favour of calculating them directly
from the SDR1 contents when necessary.
This does make a change to the behaviour of attempting to write a bad value
(invalid HPT size) to the SDR1 with an mtspr instruction. Previously, the
bad value would be stored in SDR1 and could be retrieved with a later
mfspr, but the HPT size as used by the softmmu would be, clamped to the
allowed values. Now, writing a bad value is treated as a no-op. An error
message is printed in both new and old versions.
I'm not sure which behaviour, if either, matches real hardware. I don't
think it matters that much, since it's pretty clear that if an OS writes
a bad value to SDR1, it's not going to boot.
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Reviewed-by: Alexey Kardashevskiy <aik@ozlabs.ru>
2017-02-24 08:36:44 +03:00
|
|
|
target_ulong base = ppc_hash32_hpt_base(cpu);
|
2014-03-09 22:29:41 +04:00
|
|
|
|
target/ppc: Eliminate htab_base and htab_mask variables
CPUPPCState includes fields htab_base and htab_mask which store the base
address (GPA) and size (as a mask) of the guest's hashed page table (HPT).
These are set when the SDR1 register is updated.
Keeping these in sync with the SDR1 is actually a little bit fiddly, and
probably not useful for performance, since keeping them expands the size of
CPUPPCState. It also makes some upcoming changes harder to implement.
This patch removes these fields, in favour of calculating them directly
from the SDR1 contents when necessary.
This does make a change to the behaviour of attempting to write a bad value
(invalid HPT size) to the SDR1 with an mtspr instruction. Previously, the
bad value would be stored in SDR1 and could be retrieved with a later
mfspr, but the HPT size as used by the softmmu would be, clamped to the
allowed values. Now, writing a bad value is treated as a no-op. An error
message is printed in both new and old versions.
I'm not sure which behaviour, if either, matches real hardware. I don't
think it matters that much, since it's pretty clear that if an OS writes
a bad value to SDR1, it's not going to boot.
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Reviewed-by: Alexey Kardashevskiy <aik@ozlabs.ru>
2017-02-24 08:36:44 +03:00
|
|
|
return ldl_phys(CPU(cpu)->as, base + pte_offset);
|
2013-03-12 04:31:19 +04:00
|
|
|
}
|
|
|
|
|
2016-01-14 07:33:27 +03:00
|
|
|
static inline target_ulong ppc_hash32_load_hpte1(PowerPCCPU *cpu,
|
2013-03-12 04:31:19 +04:00
|
|
|
hwaddr pte_offset)
|
|
|
|
{
|
target/ppc: Eliminate htab_base and htab_mask variables
CPUPPCState includes fields htab_base and htab_mask which store the base
address (GPA) and size (as a mask) of the guest's hashed page table (HPT).
These are set when the SDR1 register is updated.
Keeping these in sync with the SDR1 is actually a little bit fiddly, and
probably not useful for performance, since keeping them expands the size of
CPUPPCState. It also makes some upcoming changes harder to implement.
This patch removes these fields, in favour of calculating them directly
from the SDR1 contents when necessary.
This does make a change to the behaviour of attempting to write a bad value
(invalid HPT size) to the SDR1 with an mtspr instruction. Previously, the
bad value would be stored in SDR1 and could be retrieved with a later
mfspr, but the HPT size as used by the softmmu would be, clamped to the
allowed values. Now, writing a bad value is treated as a no-op. An error
message is printed in both new and old versions.
I'm not sure which behaviour, if either, matches real hardware. I don't
think it matters that much, since it's pretty clear that if an OS writes
a bad value to SDR1, it's not going to boot.
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Reviewed-by: Alexey Kardashevskiy <aik@ozlabs.ru>
2017-02-24 08:36:44 +03:00
|
|
|
target_ulong base = ppc_hash32_hpt_base(cpu);
|
2014-03-09 22:29:41 +04:00
|
|
|
|
target/ppc: Eliminate htab_base and htab_mask variables
CPUPPCState includes fields htab_base and htab_mask which store the base
address (GPA) and size (as a mask) of the guest's hashed page table (HPT).
These are set when the SDR1 register is updated.
Keeping these in sync with the SDR1 is actually a little bit fiddly, and
probably not useful for performance, since keeping them expands the size of
CPUPPCState. It also makes some upcoming changes harder to implement.
This patch removes these fields, in favour of calculating them directly
from the SDR1 contents when necessary.
This does make a change to the behaviour of attempting to write a bad value
(invalid HPT size) to the SDR1 with an mtspr instruction. Previously, the
bad value would be stored in SDR1 and could be retrieved with a later
mfspr, but the HPT size as used by the softmmu would be, clamped to the
allowed values. Now, writing a bad value is treated as a no-op. An error
message is printed in both new and old versions.
I'm not sure which behaviour, if either, matches real hardware. I don't
think it matters that much, since it's pretty clear that if an OS writes
a bad value to SDR1, it's not going to boot.
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Reviewed-by: Alexey Kardashevskiy <aik@ozlabs.ru>
2017-02-24 08:36:44 +03:00
|
|
|
return ldl_phys(CPU(cpu)->as, base + pte_offset + HASH_PTE_SIZE_32 / 2);
|
2013-03-12 04:31:19 +04:00
|
|
|
}
|
|
|
|
|
2016-01-14 07:33:27 +03:00
|
|
|
static inline void ppc_hash32_store_hpte0(PowerPCCPU *cpu,
|
2013-03-12 04:31:19 +04:00
|
|
|
hwaddr pte_offset, target_ulong pte0)
|
|
|
|
{
|
target/ppc: Eliminate htab_base and htab_mask variables
CPUPPCState includes fields htab_base and htab_mask which store the base
address (GPA) and size (as a mask) of the guest's hashed page table (HPT).
These are set when the SDR1 register is updated.
Keeping these in sync with the SDR1 is actually a little bit fiddly, and
probably not useful for performance, since keeping them expands the size of
CPUPPCState. It also makes some upcoming changes harder to implement.
This patch removes these fields, in favour of calculating them directly
from the SDR1 contents when necessary.
This does make a change to the behaviour of attempting to write a bad value
(invalid HPT size) to the SDR1 with an mtspr instruction. Previously, the
bad value would be stored in SDR1 and could be retrieved with a later
mfspr, but the HPT size as used by the softmmu would be, clamped to the
allowed values. Now, writing a bad value is treated as a no-op. An error
message is printed in both new and old versions.
I'm not sure which behaviour, if either, matches real hardware. I don't
think it matters that much, since it's pretty clear that if an OS writes
a bad value to SDR1, it's not going to boot.
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Reviewed-by: Alexey Kardashevskiy <aik@ozlabs.ru>
2017-02-24 08:36:44 +03:00
|
|
|
target_ulong base = ppc_hash32_hpt_base(cpu);
|
2014-03-09 22:29:41 +04:00
|
|
|
|
target/ppc: Eliminate htab_base and htab_mask variables
CPUPPCState includes fields htab_base and htab_mask which store the base
address (GPA) and size (as a mask) of the guest's hashed page table (HPT).
These are set when the SDR1 register is updated.
Keeping these in sync with the SDR1 is actually a little bit fiddly, and
probably not useful for performance, since keeping them expands the size of
CPUPPCState. It also makes some upcoming changes harder to implement.
This patch removes these fields, in favour of calculating them directly
from the SDR1 contents when necessary.
This does make a change to the behaviour of attempting to write a bad value
(invalid HPT size) to the SDR1 with an mtspr instruction. Previously, the
bad value would be stored in SDR1 and could be retrieved with a later
mfspr, but the HPT size as used by the softmmu would be, clamped to the
allowed values. Now, writing a bad value is treated as a no-op. An error
message is printed in both new and old versions.
I'm not sure which behaviour, if either, matches real hardware. I don't
think it matters that much, since it's pretty clear that if an OS writes
a bad value to SDR1, it's not going to boot.
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Reviewed-by: Alexey Kardashevskiy <aik@ozlabs.ru>
2017-02-24 08:36:44 +03:00
|
|
|
stl_phys(CPU(cpu)->as, base + pte_offset, pte0);
|
2013-03-12 04:31:19 +04:00
|
|
|
}
|
|
|
|
|
2016-01-14 07:33:27 +03:00
|
|
|
static inline void ppc_hash32_store_hpte1(PowerPCCPU *cpu,
|
2013-03-12 04:31:19 +04:00
|
|
|
hwaddr pte_offset, target_ulong pte1)
|
|
|
|
{
|
target/ppc: Eliminate htab_base and htab_mask variables
CPUPPCState includes fields htab_base and htab_mask which store the base
address (GPA) and size (as a mask) of the guest's hashed page table (HPT).
These are set when the SDR1 register is updated.
Keeping these in sync with the SDR1 is actually a little bit fiddly, and
probably not useful for performance, since keeping them expands the size of
CPUPPCState. It also makes some upcoming changes harder to implement.
This patch removes these fields, in favour of calculating them directly
from the SDR1 contents when necessary.
This does make a change to the behaviour of attempting to write a bad value
(invalid HPT size) to the SDR1 with an mtspr instruction. Previously, the
bad value would be stored in SDR1 and could be retrieved with a later
mfspr, but the HPT size as used by the softmmu would be, clamped to the
allowed values. Now, writing a bad value is treated as a no-op. An error
message is printed in both new and old versions.
I'm not sure which behaviour, if either, matches real hardware. I don't
think it matters that much, since it's pretty clear that if an OS writes
a bad value to SDR1, it's not going to boot.
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Reviewed-by: Alexey Kardashevskiy <aik@ozlabs.ru>
2017-02-24 08:36:44 +03:00
|
|
|
target_ulong base = ppc_hash32_hpt_base(cpu);
|
2014-03-09 22:29:41 +04:00
|
|
|
|
target/ppc: Eliminate htab_base and htab_mask variables
CPUPPCState includes fields htab_base and htab_mask which store the base
address (GPA) and size (as a mask) of the guest's hashed page table (HPT).
These are set when the SDR1 register is updated.
Keeping these in sync with the SDR1 is actually a little bit fiddly, and
probably not useful for performance, since keeping them expands the size of
CPUPPCState. It also makes some upcoming changes harder to implement.
This patch removes these fields, in favour of calculating them directly
from the SDR1 contents when necessary.
This does make a change to the behaviour of attempting to write a bad value
(invalid HPT size) to the SDR1 with an mtspr instruction. Previously, the
bad value would be stored in SDR1 and could be retrieved with a later
mfspr, but the HPT size as used by the softmmu would be, clamped to the
allowed values. Now, writing a bad value is treated as a no-op. An error
message is printed in both new and old versions.
I'm not sure which behaviour, if either, matches real hardware. I don't
think it matters that much, since it's pretty clear that if an OS writes
a bad value to SDR1, it's not going to boot.
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Reviewed-by: Alexey Kardashevskiy <aik@ozlabs.ru>
2017-02-24 08:36:44 +03:00
|
|
|
stl_phys(CPU(cpu)->as, base + pte_offset + HASH_PTE_SIZE_32 / 2, pte1);
|
2013-03-12 04:31:19 +04:00
|
|
|
}
|
|
|
|
|
2024-05-27 02:13:05 +03:00
|
|
|
static inline hwaddr get_pteg_offset32(PowerPCCPU *cpu, hwaddr hash)
|
|
|
|
{
|
|
|
|
return (hash * HASH_PTEG_SIZE_32) & ppc_hash32_hpt_mask(cpu);
|
|
|
|
}
|
|
|
|
|
2024-05-27 02:12:54 +03:00
|
|
|
static inline bool ppc_hash32_key(bool pr, target_ulong sr)
|
|
|
|
{
|
|
|
|
return pr ? (sr & SR32_KP) : (sr & SR32_KS);
|
|
|
|
}
|
|
|
|
|
2024-05-27 02:12:36 +03:00
|
|
|
static inline int ppc_hash32_prot(bool key, int pp, bool nx)
|
2024-05-13 02:28:09 +03:00
|
|
|
{
|
|
|
|
int prot;
|
|
|
|
|
2024-05-27 02:12:36 +03:00
|
|
|
if (key) {
|
2024-05-13 02:28:09 +03:00
|
|
|
switch (pp) {
|
|
|
|
case 0x0:
|
2024-05-27 02:12:36 +03:00
|
|
|
prot = 0;
|
2024-05-13 02:28:09 +03:00
|
|
|
break;
|
2024-05-27 02:12:36 +03:00
|
|
|
case 0x1:
|
2024-05-13 02:28:09 +03:00
|
|
|
case 0x3:
|
|
|
|
prot = PAGE_READ;
|
|
|
|
break;
|
2024-05-27 02:12:36 +03:00
|
|
|
case 0x2:
|
|
|
|
prot = PAGE_READ | PAGE_WRITE;
|
|
|
|
break;
|
2024-05-13 02:28:09 +03:00
|
|
|
default:
|
2024-05-27 02:12:36 +03:00
|
|
|
g_assert_not_reached();
|
2024-05-13 02:28:09 +03:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
switch (pp) {
|
|
|
|
case 0x0:
|
|
|
|
case 0x1:
|
|
|
|
case 0x2:
|
|
|
|
prot = PAGE_READ | PAGE_WRITE;
|
|
|
|
break;
|
2024-05-27 02:12:36 +03:00
|
|
|
case 0x3:
|
|
|
|
prot = PAGE_READ;
|
|
|
|
break;
|
2024-05-13 02:28:09 +03:00
|
|
|
default:
|
2024-05-27 02:12:36 +03:00
|
|
|
g_assert_not_reached();
|
2024-05-13 02:28:09 +03:00
|
|
|
}
|
|
|
|
}
|
2024-05-27 02:12:36 +03:00
|
|
|
return nx ? prot : prot | PAGE_EXEC;
|
2024-05-13 02:28:09 +03:00
|
|
|
}
|
|
|
|
|
2024-05-27 02:13:01 +03:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2013-03-12 04:31:28 +04:00
|
|
|
typedef struct {
|
|
|
|
uint32_t pte0, pte1;
|
|
|
|
} ppc_hash_pte32_t;
|
|
|
|
|
2013-03-12 04:31:07 +04:00
|
|
|
#endif /* CONFIG_USER_ONLY */
|
|
|
|
|
2016-06-29 14:47:03 +03:00
|
|
|
#endif /* MMU_HASH32_H */
|