Commit 2f882800 authored by Heiko Carstens's avatar Heiko Carstens

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: default avatarAlexander Gordeev <agordeev@linux.ibm.com>
Signed-off-by: default avatarHeiko Carstens <hca@linux.ibm.com>
parent 69700fb4
...@@ -409,9 +409,9 @@ static int base_segment_walk(unsigned long origin, unsigned long addr, ...@@ -409,9 +409,9 @@ static int base_segment_walk(unsigned long origin, unsigned long addr,
table = base_pgt_alloc(); table = base_pgt_alloc();
if (!table) if (!table)
return -ENOMEM; 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); rc = base_page_walk(table, addr, next, alloc);
if (rc) if (rc)
return rc; return rc;
...@@ -438,9 +438,9 @@ static int base_region3_walk(unsigned long origin, unsigned long addr, ...@@ -438,9 +438,9 @@ static int base_region3_walk(unsigned long origin, unsigned long addr,
table = base_crst_alloc(_SEGMENT_ENTRY_EMPTY); table = base_crst_alloc(_SEGMENT_ENTRY_EMPTY);
if (!table) if (!table)
return -ENOMEM; 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); rc = base_segment_walk(table, addr, next, alloc);
if (rc) if (rc)
return rc; return rc;
...@@ -466,9 +466,9 @@ static int base_region2_walk(unsigned long origin, unsigned long addr, ...@@ -466,9 +466,9 @@ static int base_region2_walk(unsigned long origin, unsigned long addr,
table = base_crst_alloc(_REGION3_ENTRY_EMPTY); table = base_crst_alloc(_REGION3_ENTRY_EMPTY);
if (!table) if (!table)
return -ENOMEM; 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); rc = base_region3_walk(table, addr, next, alloc);
if (rc) if (rc)
return rc; return rc;
...@@ -494,9 +494,9 @@ static int base_region1_walk(unsigned long origin, unsigned long addr, ...@@ -494,9 +494,9 @@ static int base_region1_walk(unsigned long origin, unsigned long addr,
table = base_crst_alloc(_REGION2_ENTRY_EMPTY); table = base_crst_alloc(_REGION2_ENTRY_EMPTY);
if (!table) if (!table)
return -ENOMEM; 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); rc = base_region2_walk(table, addr, next, alloc);
if (rc) if (rc)
return rc; return rc;
...@@ -515,7 +515,7 @@ static int base_region1_walk(unsigned long origin, unsigned long addr, ...@@ -515,7 +515,7 @@ static int base_region1_walk(unsigned long origin, unsigned long addr,
*/ */
void base_asce_free(unsigned long asce) void base_asce_free(unsigned long asce)
{ {
unsigned long table = asce & _ASCE_ORIGIN; unsigned long table = (unsigned long)__va(asce & _ASCE_ORIGIN);
if (!asce) if (!asce)
return; return;
...@@ -578,25 +578,25 @@ unsigned long base_asce_alloc(unsigned long addr, unsigned long num_pages) ...@@ -578,25 +578,25 @@ unsigned long base_asce_alloc(unsigned long addr, unsigned long num_pages)
if (!table) if (!table)
return 0; return 0;
rc = base_segment_walk(table, addr, end, 1); 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) { } else if (end <= _REGION2_SIZE) {
table = base_crst_alloc(_REGION3_ENTRY_EMPTY); table = base_crst_alloc(_REGION3_ENTRY_EMPTY);
if (!table) if (!table)
return 0; return 0;
rc = base_region3_walk(table, addr, end, 1); 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) { } else if (end <= _REGION1_SIZE) {
table = base_crst_alloc(_REGION2_ENTRY_EMPTY); table = base_crst_alloc(_REGION2_ENTRY_EMPTY);
if (!table) if (!table)
return 0; return 0;
rc = base_region2_walk(table, addr, end, 1); 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 { } else {
table = base_crst_alloc(_REGION1_ENTRY_EMPTY); table = base_crst_alloc(_REGION1_ENTRY_EMPTY);
if (!table) if (!table)
return 0; return 0;
rc = base_region1_walk(table, addr, end, 1); 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) { if (rc) {
base_asce_free(asce); base_asce_free(asce);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment