Merge branch 'topic/paca' into next
Bring in yet another series that touches KVM code, and might need to be merged into the kvm-ppc branch to resolve conflicts. This required some changes in pnv_power9_force_smt4_catch/release() due to the paca array becomming an array of pointers.
This commit is contained in:
@@ -48,20 +48,88 @@ static int native_register_process_table(unsigned long base, unsigned long pg_sz
|
||||
return 0;
|
||||
}
|
||||
|
||||
static __ref void *early_alloc_pgtable(unsigned long size)
|
||||
static __ref void *early_alloc_pgtable(unsigned long size, int nid,
|
||||
unsigned long region_start, unsigned long region_end)
|
||||
{
|
||||
unsigned long pa = 0;
|
||||
void *pt;
|
||||
|
||||
pt = __va(memblock_alloc_base(size, size, MEMBLOCK_ALLOC_ANYWHERE));
|
||||
if (region_start || region_end) /* has region hint */
|
||||
pa = memblock_alloc_range(size, size, region_start, region_end,
|
||||
MEMBLOCK_NONE);
|
||||
else if (nid != -1) /* has node hint */
|
||||
pa = memblock_alloc_base_nid(size, size,
|
||||
MEMBLOCK_ALLOC_ANYWHERE,
|
||||
nid, MEMBLOCK_NONE);
|
||||
|
||||
if (!pa)
|
||||
pa = memblock_alloc_base(size, size, MEMBLOCK_ALLOC_ANYWHERE);
|
||||
|
||||
BUG_ON(!pa);
|
||||
|
||||
pt = __va(pa);
|
||||
memset(pt, 0, size);
|
||||
|
||||
return pt;
|
||||
}
|
||||
|
||||
int radix__map_kernel_page(unsigned long ea, unsigned long pa,
|
||||
static int early_map_kernel_page(unsigned long ea, unsigned long pa,
|
||||
pgprot_t flags,
|
||||
unsigned int map_page_size)
|
||||
unsigned int map_page_size,
|
||||
int nid,
|
||||
unsigned long region_start, unsigned long region_end)
|
||||
{
|
||||
unsigned long pfn = pa >> PAGE_SHIFT;
|
||||
pgd_t *pgdp;
|
||||
pud_t *pudp;
|
||||
pmd_t *pmdp;
|
||||
pte_t *ptep;
|
||||
|
||||
pgdp = pgd_offset_k(ea);
|
||||
if (pgd_none(*pgdp)) {
|
||||
pudp = early_alloc_pgtable(PUD_TABLE_SIZE, nid,
|
||||
region_start, region_end);
|
||||
pgd_populate(&init_mm, pgdp, pudp);
|
||||
}
|
||||
pudp = pud_offset(pgdp, ea);
|
||||
if (map_page_size == PUD_SIZE) {
|
||||
ptep = (pte_t *)pudp;
|
||||
goto set_the_pte;
|
||||
}
|
||||
if (pud_none(*pudp)) {
|
||||
pmdp = early_alloc_pgtable(PMD_TABLE_SIZE, nid,
|
||||
region_start, region_end);
|
||||
pud_populate(&init_mm, pudp, pmdp);
|
||||
}
|
||||
pmdp = pmd_offset(pudp, ea);
|
||||
if (map_page_size == PMD_SIZE) {
|
||||
ptep = pmdp_ptep(pmdp);
|
||||
goto set_the_pte;
|
||||
}
|
||||
if (!pmd_present(*pmdp)) {
|
||||
ptep = early_alloc_pgtable(PAGE_SIZE, nid,
|
||||
region_start, region_end);
|
||||
pmd_populate_kernel(&init_mm, pmdp, ptep);
|
||||
}
|
||||
ptep = pte_offset_kernel(pmdp, ea);
|
||||
|
||||
set_the_pte:
|
||||
set_pte_at(&init_mm, ea, ptep, pfn_pte(pfn, flags));
|
||||
smp_wmb();
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* nid, region_start, and region_end are hints to try to place the page
|
||||
* table memory in the same node or region.
|
||||
*/
|
||||
static int __map_kernel_page(unsigned long ea, unsigned long pa,
|
||||
pgprot_t flags,
|
||||
unsigned int map_page_size,
|
||||
int nid,
|
||||
unsigned long region_start, unsigned long region_end)
|
||||
{
|
||||
unsigned long pfn = pa >> PAGE_SHIFT;
|
||||
pgd_t *pgdp;
|
||||
pud_t *pudp;
|
||||
pmd_t *pmdp;
|
||||
@@ -70,61 +138,48 @@ int radix__map_kernel_page(unsigned long ea, unsigned long pa,
|
||||
* Make sure task size is correct as per the max adddr
|
||||
*/
|
||||
BUILD_BUG_ON(TASK_SIZE_USER64 > RADIX_PGTABLE_RANGE);
|
||||
if (slab_is_available()) {
|
||||
pgdp = pgd_offset_k(ea);
|
||||
pudp = pud_alloc(&init_mm, pgdp, ea);
|
||||
if (!pudp)
|
||||
return -ENOMEM;
|
||||
if (map_page_size == PUD_SIZE) {
|
||||
ptep = (pte_t *)pudp;
|
||||
goto set_the_pte;
|
||||
}
|
||||
pmdp = pmd_alloc(&init_mm, pudp, ea);
|
||||
if (!pmdp)
|
||||
return -ENOMEM;
|
||||
if (map_page_size == PMD_SIZE) {
|
||||
ptep = pmdp_ptep(pmdp);
|
||||
goto set_the_pte;
|
||||
}
|
||||
ptep = pte_alloc_kernel(pmdp, ea);
|
||||
if (!ptep)
|
||||
return -ENOMEM;
|
||||
} else {
|
||||
pgdp = pgd_offset_k(ea);
|
||||
if (pgd_none(*pgdp)) {
|
||||
pudp = early_alloc_pgtable(PUD_TABLE_SIZE);
|
||||
BUG_ON(pudp == NULL);
|
||||
pgd_populate(&init_mm, pgdp, pudp);
|
||||
}
|
||||
pudp = pud_offset(pgdp, ea);
|
||||
if (map_page_size == PUD_SIZE) {
|
||||
ptep = (pte_t *)pudp;
|
||||
goto set_the_pte;
|
||||
}
|
||||
if (pud_none(*pudp)) {
|
||||
pmdp = early_alloc_pgtable(PMD_TABLE_SIZE);
|
||||
BUG_ON(pmdp == NULL);
|
||||
pud_populate(&init_mm, pudp, pmdp);
|
||||
}
|
||||
pmdp = pmd_offset(pudp, ea);
|
||||
if (map_page_size == PMD_SIZE) {
|
||||
ptep = pmdp_ptep(pmdp);
|
||||
goto set_the_pte;
|
||||
}
|
||||
if (!pmd_present(*pmdp)) {
|
||||
ptep = early_alloc_pgtable(PAGE_SIZE);
|
||||
BUG_ON(ptep == NULL);
|
||||
pmd_populate_kernel(&init_mm, pmdp, ptep);
|
||||
}
|
||||
ptep = pte_offset_kernel(pmdp, ea);
|
||||
|
||||
if (unlikely(!slab_is_available()))
|
||||
return early_map_kernel_page(ea, pa, flags, map_page_size,
|
||||
nid, region_start, region_end);
|
||||
|
||||
/*
|
||||
* Should make page table allocation functions be able to take a
|
||||
* node, so we can place kernel page tables on the right nodes after
|
||||
* boot.
|
||||
*/
|
||||
pgdp = pgd_offset_k(ea);
|
||||
pudp = pud_alloc(&init_mm, pgdp, ea);
|
||||
if (!pudp)
|
||||
return -ENOMEM;
|
||||
if (map_page_size == PUD_SIZE) {
|
||||
ptep = (pte_t *)pudp;
|
||||
goto set_the_pte;
|
||||
}
|
||||
pmdp = pmd_alloc(&init_mm, pudp, ea);
|
||||
if (!pmdp)
|
||||
return -ENOMEM;
|
||||
if (map_page_size == PMD_SIZE) {
|
||||
ptep = pmdp_ptep(pmdp);
|
||||
goto set_the_pte;
|
||||
}
|
||||
ptep = pte_alloc_kernel(pmdp, ea);
|
||||
if (!ptep)
|
||||
return -ENOMEM;
|
||||
|
||||
set_the_pte:
|
||||
set_pte_at(&init_mm, ea, ptep, pfn_pte(pa >> PAGE_SHIFT, flags));
|
||||
set_pte_at(&init_mm, ea, ptep, pfn_pte(pfn, flags));
|
||||
smp_wmb();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int radix__map_kernel_page(unsigned long ea, unsigned long pa,
|
||||
pgprot_t flags,
|
||||
unsigned int map_page_size)
|
||||
{
|
||||
return __map_kernel_page(ea, pa, flags, map_page_size, -1, 0, 0);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_STRICT_KERNEL_RWX
|
||||
void radix__change_memory_range(unsigned long start, unsigned long end,
|
||||
unsigned long clear)
|
||||
@@ -211,7 +266,8 @@ static inline void __meminit print_mapping(unsigned long start,
|
||||
}
|
||||
|
||||
static int __meminit create_physical_mapping(unsigned long start,
|
||||
unsigned long end)
|
||||
unsigned long end,
|
||||
int nid)
|
||||
{
|
||||
unsigned long vaddr, addr, mapping_size = 0;
|
||||
pgprot_t prot;
|
||||
@@ -267,7 +323,7 @@ retry:
|
||||
else
|
||||
prot = PAGE_KERNEL;
|
||||
|
||||
rc = radix__map_kernel_page(vaddr, addr, prot, mapping_size);
|
||||
rc = __map_kernel_page(vaddr, addr, prot, mapping_size, nid, start, end);
|
||||
if (rc)
|
||||
return rc;
|
||||
}
|
||||
@@ -276,7 +332,7 @@ retry:
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __init radix_init_pgtable(void)
|
||||
void __init radix_init_pgtable(void)
|
||||
{
|
||||
unsigned long rts_field;
|
||||
struct memblock_region *reg;
|
||||
@@ -286,9 +342,16 @@ static void __init radix_init_pgtable(void)
|
||||
/*
|
||||
* Create the linear mapping, using standard page size for now
|
||||
*/
|
||||
for_each_memblock(memory, reg)
|
||||
for_each_memblock(memory, reg) {
|
||||
/*
|
||||
* The memblock allocator is up at this point, so the
|
||||
* page tables will be allocated within the range. No
|
||||
* need or a node (which we don't have yet).
|
||||
*/
|
||||
WARN_ON(create_physical_mapping(reg->base,
|
||||
reg->base + reg->size));
|
||||
reg->base + reg->size,
|
||||
-1));
|
||||
}
|
||||
|
||||
/* Find out how many PID bits are supported */
|
||||
if (cpu_has_feature(CPU_FTR_HVMODE)) {
|
||||
@@ -317,7 +380,7 @@ static void __init radix_init_pgtable(void)
|
||||
* host.
|
||||
*/
|
||||
BUG_ON(PRTB_SIZE_SHIFT > 36);
|
||||
process_tb = early_alloc_pgtable(1UL << PRTB_SIZE_SHIFT);
|
||||
process_tb = early_alloc_pgtable(1UL << PRTB_SIZE_SHIFT, -1, 0, 0);
|
||||
/*
|
||||
* Fill in the process table.
|
||||
*/
|
||||
@@ -705,8 +768,8 @@ static int __meminit stop_machine_change_mapping(void *data)
|
||||
|
||||
spin_unlock(&init_mm.page_table_lock);
|
||||
pte_clear(&init_mm, params->aligned_start, params->pte);
|
||||
create_physical_mapping(params->aligned_start, params->start);
|
||||
create_physical_mapping(params->end, params->aligned_end);
|
||||
create_physical_mapping(params->aligned_start, params->start, -1);
|
||||
create_physical_mapping(params->end, params->aligned_end, -1);
|
||||
spin_lock(&init_mm.page_table_lock);
|
||||
return 0;
|
||||
}
|
||||
@@ -863,9 +926,9 @@ static void __meminit remove_pagetable(unsigned long start, unsigned long end)
|
||||
radix__flush_tlb_kernel_range(start, end);
|
||||
}
|
||||
|
||||
int __meminit radix__create_section_mapping(unsigned long start, unsigned long end)
|
||||
int __meminit radix__create_section_mapping(unsigned long start, unsigned long end, int nid)
|
||||
{
|
||||
return create_physical_mapping(start, end);
|
||||
return create_physical_mapping(start, end, nid);
|
||||
}
|
||||
|
||||
int __meminit radix__remove_section_mapping(unsigned long start, unsigned long end)
|
||||
@@ -876,14 +939,25 @@ int __meminit radix__remove_section_mapping(unsigned long start, unsigned long e
|
||||
#endif /* CONFIG_MEMORY_HOTPLUG */
|
||||
|
||||
#ifdef CONFIG_SPARSEMEM_VMEMMAP
|
||||
static int __map_kernel_page_nid(unsigned long ea, unsigned long pa,
|
||||
pgprot_t flags, unsigned int map_page_size,
|
||||
int nid)
|
||||
{
|
||||
return __map_kernel_page(ea, pa, flags, map_page_size, nid, 0, 0);
|
||||
}
|
||||
|
||||
int __meminit radix__vmemmap_create_mapping(unsigned long start,
|
||||
unsigned long page_size,
|
||||
unsigned long phys)
|
||||
{
|
||||
/* Create a PTE encoding */
|
||||
unsigned long flags = _PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_KERNEL_RW;
|
||||
int nid = early_pfn_to_nid(phys >> PAGE_SHIFT);
|
||||
int ret;
|
||||
|
||||
ret = __map_kernel_page_nid(start, phys, __pgprot(flags), page_size, nid);
|
||||
BUG_ON(ret);
|
||||
|
||||
BUG_ON(radix__map_kernel_page(start, phys, __pgprot(flags), page_size));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user