Skip to content

Commit cc3d294

Browse files
paulusmackmpe
authored andcommitted
powerpc/64: Enable use of radix MMU under hypervisor on POWER9
To use radix as a guest, we first need to tell the hypervisor via the ibm,client-architecture call first that we support POWER9 and architecture v3.00, and that we can do either radix or hash and that we would like to choose later using an hcall (the H_REGISTER_PROC_TBL hcall). Then we need to check whether the hypervisor agreed to us using radix. We need to do this very early on in the kernel boot process before any of the MMU initialization is done. If the hypervisor doesn't agree, we can't use radix and therefore clear the radix MMU feature bit. Later, when we have set up our process table, which points to the radix tree for each process, we need to install that using the H_REGISTER_PROC_TBL hcall. Signed-off-by: Paul Mackerras <[email protected]> Signed-off-by: Michael Ellerman <[email protected]>
1 parent 3f4ab2f commit cc3d294

File tree

7 files changed

+81
-6
lines changed

7 files changed

+81
-6
lines changed

arch/powerpc/include/asm/book3s/64/mmu.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,5 +138,11 @@ static inline void setup_initial_memory_limit(phys_addr_t first_memblock_base,
138138
extern int (*register_process_table)(unsigned long base, unsigned long page_size,
139139
unsigned long tbl_size);
140140

141+
#ifdef CONFIG_PPC_PSERIES
142+
extern void radix_init_pseries(void);
143+
#else
144+
static inline void radix_init_pseries(void) { };
145+
#endif
146+
141147
#endif /* __ASSEMBLY__ */
142148
#endif /* _ASM_POWERPC_BOOK3S_64_MMU_H_ */

arch/powerpc/include/asm/hvcall.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -276,6 +276,7 @@
276276
#define H_GET_MPP_X 0x314
277277
#define H_SET_MODE 0x31C
278278
#define H_CLEAR_HPT 0x358
279+
#define H_REGISTER_PROC_TBL 0x37C
279280
#define H_SIGNAL_SYS_RESET 0x380
280281
#define MAX_HCALL_OPCODE H_SIGNAL_SYS_RESET
281282

@@ -313,6 +314,16 @@
313314
#define H_SIGNAL_SYS_RESET_ALL_OTHERS -2
314315
/* >= 0 values are CPU number */
315316

317+
/* Flag values used in H_REGISTER_PROC_TBL hcall */
318+
#define PROC_TABLE_OP_MASK 0x18
319+
#define PROC_TABLE_DEREG 0x10
320+
#define PROC_TABLE_NEW 0x18
321+
#define PROC_TABLE_TYPE_MASK 0x06
322+
#define PROC_TABLE_HPT_SLB 0x00
323+
#define PROC_TABLE_HPT_PT 0x02
324+
#define PROC_TABLE_RADIX 0x04
325+
#define PROC_TABLE_GTSE 0x01
326+
316327
#ifndef __ASSEMBLY__
317328

318329
/**

arch/powerpc/include/asm/prom.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,8 @@ struct of_drconf_cell {
121121
#define OV1_PPC_2_06 0x02 /* set if we support PowerPC 2.06 */
122122
#define OV1_PPC_2_07 0x01 /* set if we support PowerPC 2.07 */
123123

124+
#define OV1_PPC_3_00 0x80 /* set if we support PowerPC 3.00 */
125+
124126
/* Option vector 2: Open Firmware options supported */
125127
#define OV2_REAL_MODE 0x20 /* set if we want OF in real mode */
126128

@@ -155,6 +157,13 @@ struct of_drconf_cell {
155157
#define OV5_PFO_HW_842 0x1140 /* PFO Compression Accelerator */
156158
#define OV5_PFO_HW_ENCR 0x1120 /* PFO Encryption Accelerator */
157159
#define OV5_SUB_PROCESSORS 0x1501 /* 1,2,or 4 Sub-Processors supported */
160+
#define OV5_XIVE_EXPLOIT 0x1701 /* XIVE exploitation supported */
161+
#define OV5_MMU_RADIX_300 0x1880 /* ISA v3.00 radix MMU supported */
162+
#define OV5_MMU_HASH_300 0x1840 /* ISA v3.00 hash MMU supported */
163+
#define OV5_MMU_SEGM_RADIX 0x1820 /* radix mode (no segmentation) */
164+
#define OV5_MMU_PROC_TBL 0x1810 /* hcall selects SLB or proc table */
165+
#define OV5_MMU_SLB 0x1800 /* always use SLB */
166+
#define OV5_MMU_GTSE 0x1808 /* Guest translation shootdown */
158167

159168
/* Option Vector 6: IBM PAPR hints */
160169
#define OV6_LINUX 0x02 /* Linux is our OS */

arch/powerpc/kernel/prom_init.c

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -649,6 +649,7 @@ static void __init early_cmdline_parse(void)
649649
struct option_vector1 {
650650
u8 byte1;
651651
u8 arch_versions;
652+
u8 arch_versions3;
652653
} __packed;
653654

654655
struct option_vector2 {
@@ -691,6 +692,9 @@ struct option_vector5 {
691692
u8 reserved2;
692693
__be16 reserved3;
693694
u8 subprocessors;
695+
u8 byte22;
696+
u8 intarch;
697+
u8 mmu;
694698
} __packed;
695699

696700
struct option_vector6 {
@@ -700,7 +704,7 @@ struct option_vector6 {
700704
} __packed;
701705

702706
struct ibm_arch_vec {
703-
struct { u32 mask, val; } pvrs[10];
707+
struct { u32 mask, val; } pvrs[12];
704708

705709
u8 num_vectors;
706710

@@ -749,6 +753,14 @@ struct ibm_arch_vec __cacheline_aligned ibm_architecture_vec = {
749753
.mask = cpu_to_be32(0xffff0000), /* POWER8 */
750754
.val = cpu_to_be32(0x004d0000),
751755
},
756+
{
757+
.mask = cpu_to_be32(0xffff0000), /* POWER9 */
758+
.val = cpu_to_be32(0x004e0000),
759+
},
760+
{
761+
.mask = cpu_to_be32(0xffffffff), /* all 3.00-compliant */
762+
.val = cpu_to_be32(0x0f000005),
763+
},
752764
{
753765
.mask = cpu_to_be32(0xffffffff), /* all 2.07-compliant */
754766
.val = cpu_to_be32(0x0f000004),
@@ -774,6 +786,7 @@ struct ibm_arch_vec __cacheline_aligned ibm_architecture_vec = {
774786
.byte1 = 0,
775787
.arch_versions = OV1_PPC_2_00 | OV1_PPC_2_01 | OV1_PPC_2_02 | OV1_PPC_2_03 |
776788
OV1_PPC_2_04 | OV1_PPC_2_05 | OV1_PPC_2_06 | OV1_PPC_2_07,
789+
.arch_versions3 = OV1_PPC_3_00,
777790
},
778791

779792
.vec2_len = VECTOR_LENGTH(sizeof(struct option_vector2)),
@@ -836,6 +849,9 @@ struct ibm_arch_vec __cacheline_aligned ibm_architecture_vec = {
836849
.reserved2 = 0,
837850
.reserved3 = 0,
838851
.subprocessors = 1,
852+
.intarch = 0,
853+
.mmu = OV5_FEAT(OV5_MMU_RADIX_300) | OV5_FEAT(OV5_MMU_HASH_300) |
854+
OV5_FEAT(OV5_MMU_PROC_TBL) | OV5_FEAT(OV5_MMU_GTSE),
839855
},
840856

841857
/* option vector 6: IBM PAPR hints */

arch/powerpc/mm/init_64.c

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -347,10 +347,9 @@ static int __init parse_disable_radix(char *p)
347347
early_param("disable_radix", parse_disable_radix);
348348

349349
/*
350-
* If we're running under a hypervisor, we currently can't do radix
351-
* since we don't have the code to do the H_REGISTER_PROC_TBL hcall.
352-
* We tell that we're running under a hypervisor by looking for the
353-
* /chosen/ibm,architecture-vec-5 property.
350+
* If we're running under a hypervisor, we need to check the contents of
351+
* /chosen/ibm,architecture-vec-5 to see if the hypervisor is willing to do
352+
* radix. If not, we clear the radix feature bit so we fall back to hash.
354353
*/
355354
static void early_check_vec5(void)
356355
{
@@ -365,7 +364,10 @@ static void early_check_vec5(void)
365364
vec5 = of_get_flat_dt_prop(chosen, "ibm,architecture-vec-5", &size);
366365
if (!vec5)
367366
return;
368-
cur_cpu_spec->mmu_features &= ~MMU_FTR_TYPE_RADIX;
367+
if (size <= OV5_INDX(OV5_MMU_RADIX_300) ||
368+
!(vec5[OV5_INDX(OV5_MMU_RADIX_300)] & OV5_FEAT(OV5_MMU_RADIX_300)))
369+
/* Hypervisor doesn't support radix */
370+
cur_cpu_spec->mmu_features &= ~MMU_FTR_TYPE_RADIX;
369371
}
370372

371373
void __init mmu_early_init_devtree(void)

arch/powerpc/mm/pgtable-radix.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -401,6 +401,8 @@ void __init radix__early_init_mmu(void)
401401
mtspr(SPRN_LPCR, lpcr | LPCR_UPRT | LPCR_HR);
402402
radix_init_partition_table();
403403
radix_init_amor();
404+
} else {
405+
radix_init_pseries();
404406
}
405407

406408
memblock_set_current_limit(MEMBLOCK_ALLOC_ANYWHERE);

arch/powerpc/platforms/pseries/lpar.c

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -609,6 +609,29 @@ static int __init disable_bulk_remove(char *str)
609609

610610
__setup("bulk_remove=", disable_bulk_remove);
611611

612+
/* Actually only used for radix, so far */
613+
static int pseries_lpar_register_process_table(unsigned long base,
614+
unsigned long page_size, unsigned long table_size)
615+
{
616+
long rc;
617+
unsigned long flags = PROC_TABLE_NEW;
618+
619+
if (radix_enabled())
620+
flags |= PROC_TABLE_RADIX | PROC_TABLE_GTSE;
621+
for (;;) {
622+
rc = plpar_hcall_norets(H_REGISTER_PROC_TBL, flags, base,
623+
page_size, table_size);
624+
if (!H_IS_LONG_BUSY(rc))
625+
break;
626+
mdelay(get_longbusy_msecs(rc));
627+
}
628+
if (rc != H_SUCCESS) {
629+
pr_err("Failed to register process table (rc=%ld)\n", rc);
630+
BUG();
631+
}
632+
return rc;
633+
}
634+
612635
void __init hpte_init_pseries(void)
613636
{
614637
mmu_hash_ops.hpte_invalidate = pSeries_lpar_hpte_invalidate;
@@ -622,6 +645,12 @@ void __init hpte_init_pseries(void)
622645
mmu_hash_ops.hugepage_invalidate = pSeries_lpar_hugepage_invalidate;
623646
}
624647

648+
void radix_init_pseries(void)
649+
{
650+
pr_info("Using radix MMU under hypervisor\n");
651+
register_process_table = pseries_lpar_register_process_table;
652+
}
653+
625654
#ifdef CONFIG_PPC_SMLPAR
626655
#define CMO_FREE_HINT_DEFAULT 1
627656
static int cmo_free_hint_flag = CMO_FREE_HINT_DEFAULT;

0 commit comments

Comments
 (0)