zipl: Fixing program check handler function

The program check handler has a bug in calculating the address of the target
to jump to. Furthermore the use of relative addresses in the exception table
can lead to situations where the (calculated) fault is not unique. Storing
the absolute address of the fault and target in the exception table solves
both problems.
This patch is intended to:
  - Modify exception table to store the absolute address of 'fault' and
    'target' points
  - Adjust program check handler function pgm_check_handler_fn() accordingly

Signed-off-by: Mikhail Zaslonko <zaslonko@linux.vnet.ibm.com>
Reviewed-by: Heiko Carstens <heiko.carstens@de.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
This commit is contained in:
Mikhail Zaslonko
2018-04-09 10:50:52 +02:00
committed by Jan Höppner
parent edaad2a927
commit 9f2e406525
2 changed files with 6 additions and 9 deletions

View File

@@ -23,8 +23,8 @@ extern char __ex_table_start[];
extern char __ex_table_stop[];
struct ex_table_entry {
int fault;
int target;
unsigned int fault;
unsigned int target;
};
#define MEM_ALLOC_START ((unsigned long) __heap_start)
@@ -310,16 +310,13 @@ void pgm_check_handler_fn(void)
struct ex_table_entry *ex_table = (void *) __ex_table_start;
struct psw_t *psw_old = &S390_lowcore.program_old_psw;
int i, ex_table_cnt;
unsigned long fault, target;
ex_table_cnt = (__ex_table_stop - __ex_table_start)
/ sizeof(struct ex_table_entry);
for (i = 0; i < ex_table_cnt; i++) {
fault = __pa(&ex_table[i]) + ex_table[i].fault;
if (fault == psw_old->addr) {
target = __pa(&ex_table[i]) + ex_table[i].target;
psw_old->addr = target;
if (ex_table[i].fault == psw_old->addr) {
psw_old->addr = ex_table[i].target;
return;
}
}

View File

@@ -25,8 +25,8 @@
#define EX_TABLE(_fault, _target) \
".section .ex_table,\"a\"\n" \
".align 4\n" \
".long (" #_fault ") - .\n" \
".long (" #_target ") - .\n" \
".long (" #_fault ")\n" \
".long (" #_target ")\n" \
".previous\n"
struct psw_t {