mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-12-16 07:24:39 +08:00
s390/pgalloc: add virt/phys address handling to base asce functions
The base asce functions create/free page tables open-coded to make sure that the returned asce and page tables do not make use of any enhanced DAT features like e.g. large pages. This is required for some I/O functions that use an asce, like e.g. some service call requests. Handling of virtual vs physical addresses is missing; therefore add that now. Note: this currently doesn't fix a real bug, since virtual addresses are indentical to physical ones. Reviewed-by: Alexander Gordeev <agordeev@linux.ibm.com> Signed-off-by: Heiko Carstens <hca@linux.ibm.com>
This commit is contained in:
parent
69700fb438
commit
2f882800f6
@ -409,9 +409,9 @@ static int base_segment_walk(unsigned long origin, unsigned long addr,
|
||||
table = base_pgt_alloc();
|
||||
if (!table)
|
||||
return -ENOMEM;
|
||||
*ste = table | _SEGMENT_ENTRY;
|
||||
*ste = __pa(table) | _SEGMENT_ENTRY;
|
||||
}
|
||||
table = *ste & _SEGMENT_ENTRY_ORIGIN;
|
||||
table = (unsigned long)__va(*ste & _SEGMENT_ENTRY_ORIGIN);
|
||||
rc = base_page_walk(table, addr, next, alloc);
|
||||
if (rc)
|
||||
return rc;
|
||||
@ -438,9 +438,9 @@ static int base_region3_walk(unsigned long origin, unsigned long addr,
|
||||
table = base_crst_alloc(_SEGMENT_ENTRY_EMPTY);
|
||||
if (!table)
|
||||
return -ENOMEM;
|
||||
*rtte = table | _REGION3_ENTRY;
|
||||
*rtte = __pa(table) | _REGION3_ENTRY;
|
||||
}
|
||||
table = *rtte & _REGION_ENTRY_ORIGIN;
|
||||
table = (unsigned long)__va(*rtte & _REGION_ENTRY_ORIGIN);
|
||||
rc = base_segment_walk(table, addr, next, alloc);
|
||||
if (rc)
|
||||
return rc;
|
||||
@ -466,9 +466,9 @@ static int base_region2_walk(unsigned long origin, unsigned long addr,
|
||||
table = base_crst_alloc(_REGION3_ENTRY_EMPTY);
|
||||
if (!table)
|
||||
return -ENOMEM;
|
||||
*rste = table | _REGION2_ENTRY;
|
||||
*rste = __pa(table) | _REGION2_ENTRY;
|
||||
}
|
||||
table = *rste & _REGION_ENTRY_ORIGIN;
|
||||
table = (unsigned long)__va(*rste & _REGION_ENTRY_ORIGIN);
|
||||
rc = base_region3_walk(table, addr, next, alloc);
|
||||
if (rc)
|
||||
return rc;
|
||||
@ -494,9 +494,9 @@ static int base_region1_walk(unsigned long origin, unsigned long addr,
|
||||
table = base_crst_alloc(_REGION2_ENTRY_EMPTY);
|
||||
if (!table)
|
||||
return -ENOMEM;
|
||||
*rfte = table | _REGION1_ENTRY;
|
||||
*rfte = __pa(table) | _REGION1_ENTRY;
|
||||
}
|
||||
table = *rfte & _REGION_ENTRY_ORIGIN;
|
||||
table = (unsigned long)__va(*rfte & _REGION_ENTRY_ORIGIN);
|
||||
rc = base_region2_walk(table, addr, next, alloc);
|
||||
if (rc)
|
||||
return rc;
|
||||
@ -515,7 +515,7 @@ static int base_region1_walk(unsigned long origin, unsigned long addr,
|
||||
*/
|
||||
void base_asce_free(unsigned long asce)
|
||||
{
|
||||
unsigned long table = asce & _ASCE_ORIGIN;
|
||||
unsigned long table = (unsigned long)__va(asce & _ASCE_ORIGIN);
|
||||
|
||||
if (!asce)
|
||||
return;
|
||||
@ -578,25 +578,25 @@ unsigned long base_asce_alloc(unsigned long addr, unsigned long num_pages)
|
||||
if (!table)
|
||||
return 0;
|
||||
rc = base_segment_walk(table, addr, end, 1);
|
||||
asce = table | _ASCE_TYPE_SEGMENT | _ASCE_TABLE_LENGTH;
|
||||
asce = __pa(table) | _ASCE_TYPE_SEGMENT | _ASCE_TABLE_LENGTH;
|
||||
} else if (end <= _REGION2_SIZE) {
|
||||
table = base_crst_alloc(_REGION3_ENTRY_EMPTY);
|
||||
if (!table)
|
||||
return 0;
|
||||
rc = base_region3_walk(table, addr, end, 1);
|
||||
asce = table | _ASCE_TYPE_REGION3 | _ASCE_TABLE_LENGTH;
|
||||
asce = __pa(table) | _ASCE_TYPE_REGION3 | _ASCE_TABLE_LENGTH;
|
||||
} else if (end <= _REGION1_SIZE) {
|
||||
table = base_crst_alloc(_REGION2_ENTRY_EMPTY);
|
||||
if (!table)
|
||||
return 0;
|
||||
rc = base_region2_walk(table, addr, end, 1);
|
||||
asce = table | _ASCE_TYPE_REGION2 | _ASCE_TABLE_LENGTH;
|
||||
asce = __pa(table) | _ASCE_TYPE_REGION2 | _ASCE_TABLE_LENGTH;
|
||||
} else {
|
||||
table = base_crst_alloc(_REGION1_ENTRY_EMPTY);
|
||||
if (!table)
|
||||
return 0;
|
||||
rc = base_region1_walk(table, addr, end, 1);
|
||||
asce = table | _ASCE_TYPE_REGION1 | _ASCE_TABLE_LENGTH;
|
||||
asce = __pa(table) | _ASCE_TYPE_REGION1 | _ASCE_TABLE_LENGTH;
|
||||
}
|
||||
if (rc) {
|
||||
base_asce_free(asce);
|
||||
|
Loading…
Reference in New Issue
Block a user