aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTakao Indoh <indou.takao@jp.fujitsu.com>2009-11-19 16:39:22 -0500
committerTony Luck <tony.luck@intel.com>2009-12-14 19:37:58 -0500
commit9ee27c76393394c7fb1ddeca3f1622d4537185a0 (patch)
treed211485178ade9358e830dc21506db21f6d91cf5
parent09b366b78c9602f53344c269eac608fd6e24d670 (diff)
[IA64] Save I-resources to ia64_sal_os_state
This is a patch related to this discussion. http://www.spinics.net/lists/linux-ia64/msg07605.html When INIT is sent, ip/psr/pfs register is stored to the I-resources (iip/ipsr/ifs registers), and they are copied in the min-state save area(pmsa_{iip,ipsr,ifs}). Therefore, in creating pt_regs at ia64_mca_modify_original_stack(), cr_{iip,ipsr,ifs} should be derived from pmsa_{iip,ipsr,ifs}. But current code copies pmsa_{xip,xpsr,xfs} to cr_{iip,ipsr,ifs} when PSR.ic is 0. finish_pt_regs(struct pt_regs *regs, const pal_min_state_area_t *ms, unsigned long *nat) { (snip) if (ia64_psr(regs)->ic) { regs->cr_iip = ms->pmsa_iip; regs->cr_ipsr = ms->pmsa_ipsr; regs->cr_ifs = ms->pmsa_ifs; } else { regs->cr_iip = ms->pmsa_xip; regs->cr_ipsr = ms->pmsa_xpsr; regs->cr_ifs = ms->pmsa_xfs; } It's ok when PSR.ic is not 0. But when PSR.ic is 0, this could be a problem when we investigate kernel as the value of regs->cr_iip does not point to where INIT really interrupted. At first I tried to change finish_pt_regs() so that it uses always pmsa_{iip,ipsr,ifs} for cr_{iip,ipsr,ifs}, but Keith Owens pointed out it could cause another problem if I change it. >The only problem I can think of is an MCA/INIT >arriving while code like SAVE_MIN or SAVE_REST is executing. Back >tracing at that point using pmsa_iip is going to be a problem, you have >no idea what state the registers or stack are in. I confirmed he was right, so I decided to keep it as-is and to save pmsa_{iip,ipsr,ifs} to ia64_sal_os_state for debugging. An attached patch is just adding new members into ia64_sal_os_state to save pmsa_{iip,ipsr,ifs}. Signed-off-by: Takao Indoh <indou.takao@jp.fujitsu.com> Signed-off-by: Tony Luck <tony.luck@intel.com>
-rw-r--r--arch/ia64/include/asm/mca.h5
-rw-r--r--arch/ia64/kernel/mca.c11
2 files changed, 13 insertions, 3 deletions
diff --git a/arch/ia64/include/asm/mca.h b/arch/ia64/include/asm/mca.h
index c171cdf0a789..43f96ab18fa0 100644
--- a/arch/ia64/include/asm/mca.h
+++ b/arch/ia64/include/asm/mca.h
@@ -106,6 +106,11 @@ struct ia64_sal_os_state {
106 unsigned long os_status; /* OS status to SAL, enum below */ 106 unsigned long os_status; /* OS status to SAL, enum below */
107 unsigned long context; /* 0 if return to same context 107 unsigned long context; /* 0 if return to same context
108 1 if return to new context */ 108 1 if return to new context */
109
110 /* I-resources */
111 unsigned long iip;
112 unsigned long ipsr;
113 unsigned long ifs;
109}; 114};
110 115
111enum { 116enum {
diff --git a/arch/ia64/kernel/mca.c b/arch/ia64/kernel/mca.c
index 496ac7a99488..32f2639e9b0a 100644
--- a/arch/ia64/kernel/mca.c
+++ b/arch/ia64/kernel/mca.c
@@ -888,9 +888,10 @@ ia64_mca_modify_comm(const struct task_struct *previous_current)
888} 888}
889 889
890static void 890static void
891finish_pt_regs(struct pt_regs *regs, const pal_min_state_area_t *ms, 891finish_pt_regs(struct pt_regs *regs, struct ia64_sal_os_state *sos,
892 unsigned long *nat) 892 unsigned long *nat)
893{ 893{
894 const pal_min_state_area_t *ms = sos->pal_min_state;
894 const u64 *bank; 895 const u64 *bank;
895 896
896 /* If ipsr.ic then use pmsa_{iip,ipsr,ifs}, else use 897 /* If ipsr.ic then use pmsa_{iip,ipsr,ifs}, else use
@@ -904,6 +905,10 @@ finish_pt_regs(struct pt_regs *regs, const pal_min_state_area_t *ms,
904 regs->cr_iip = ms->pmsa_xip; 905 regs->cr_iip = ms->pmsa_xip;
905 regs->cr_ipsr = ms->pmsa_xpsr; 906 regs->cr_ipsr = ms->pmsa_xpsr;
906 regs->cr_ifs = ms->pmsa_xfs; 907 regs->cr_ifs = ms->pmsa_xfs;
908
909 sos->iip = ms->pmsa_iip;
910 sos->ipsr = ms->pmsa_ipsr;
911 sos->ifs = ms->pmsa_ifs;
907 } 912 }
908 regs->pr = ms->pmsa_pr; 913 regs->pr = ms->pmsa_pr;
909 regs->b0 = ms->pmsa_br0; 914 regs->b0 = ms->pmsa_br0;
@@ -1079,7 +1084,7 @@ ia64_mca_modify_original_stack(struct pt_regs *regs,
1079 memcpy(old_regs, regs, sizeof(*regs)); 1084 memcpy(old_regs, regs, sizeof(*regs));
1080 old_regs->loadrs = loadrs; 1085 old_regs->loadrs = loadrs;
1081 old_unat = old_regs->ar_unat; 1086 old_unat = old_regs->ar_unat;
1082 finish_pt_regs(old_regs, ms, &old_unat); 1087 finish_pt_regs(old_regs, sos, &old_unat);
1083 1088
1084 /* Next stack a struct switch_stack. mca_asm.S built a partial 1089 /* Next stack a struct switch_stack. mca_asm.S built a partial
1085 * switch_stack, copy it and fill in the blanks using pt_regs and 1090 * switch_stack, copy it and fill in the blanks using pt_regs and
@@ -1150,7 +1155,7 @@ no_mod:
1150 mprintk(KERN_INFO "cpu %d, %s %s, original stack not modified\n", 1155 mprintk(KERN_INFO "cpu %d, %s %s, original stack not modified\n",
1151 smp_processor_id(), type, msg); 1156 smp_processor_id(), type, msg);
1152 old_unat = regs->ar_unat; 1157 old_unat = regs->ar_unat;
1153 finish_pt_regs(regs, ms, &old_unat); 1158 finish_pt_regs(regs, sos, &old_unat);
1154 return previous_current; 1159 return previous_current;
1155} 1160}
1156 1161