https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70220
--- Comment #7 from Wink Saville <wink at saville dot com> ---
(In reply to H.J. Lu from comment #3)
> (In reply to Wink Saville from comment #2)
> > (In reply to H.J. Lu from comment #1)
> > > (In reply to Wink Saville from comment #0)
> > > > I have identified one possible problem and with this scheme, what if the
> > > > compiler needs to setup a stack frame by pushing rbp and then moving
> > > > rsp to
> > > > rbp, how would that case be handled.
> > >
> > > Why should be it a problem unless you don't want to restore RSP and RBP
> > > to its original values upon returning from ISR. Please provide an example
> > > here.
> >
> > Here a possible example, I added a printf and local variables to
> > timer_reschedule_isr:
> >
> > void timer_reschedule_isr(struct intr_frame* frame) {
> > __asm__ volatile(""::: "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "rbp",
> > "r8", "r9", "r10", "r11", "r12", "r13", "r14",
> > "r15");
> >
>
> > If I now remove "rbp" from the clobber list it compiles:
> >
>
> rbp is special. Will remove rbp from the clobber list cause any
> problems here?
As I see it removing rbp from the clober list is a problem. In the current code
it changes the order of the pushes so struct full_stack_frame would be wrong.
For example I have two routines "reschedule_isr" is saving "rbp" and
"timer_reschedule_isr" is not saving "rbp":
__attribute__((__interrupt__))
void reschedule_isr(struct intr_frame* frame) {
__asm__ volatile(""::: "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "rbp",
"r8", "r9", "r10", "r11", "r12", "r13", "r14",
"r15");
tcb_x86 *ptcb = thread_scheduler((ac_u8*)get_sp(), get_ss());
__asm__ volatile("movq %0, %%rsp;" :: "rm" (ptcb->sp) : "rsp");
__asm__ volatile("movw %0, %%ss;" :: "rm" (ptcb->ss));
set_apic_timer_initial_count(ptcb->slice);
}
__attribute__((__interrupt__))
void timer_reschedule_isr(struct intr_frame* frame) {
__asm__ volatile(""::: "rax", "rbx", "rcx", "rdx", "rsi", "rdi", // "rbp",
"r8", "r9", "r10", "r11", "r12", "r13", "r14",
"r15");
volatile ac_u64 array[3];
array[2] = get_sp();
ac_printf("timer_reschedule_isr array[0]=%p\n", array[2]);
tcb_x86 *ptcb = thread_scheduler((ac_u8*)get_sp(), get_ss());
__asm__ volatile("movq %0, %%rsp;" :: "rm" (ptcb->sp) : "rsp");
__asm__ volatile("movw %0, %%ss;" :: "rm" (ptcb->ss));
set_apic_timer_initial_count(ptcb->slice);
__atomic_add_fetch(&timer_reschedule_isr_counter, 1, __ATOMIC_RELEASE);
send_apic_eoi();
}
If you look at the prologue/epilogues we see that they are different so that
means struct full_stack_frame would have to be different for the two routines
and that makes the programmers job very hard:
00000000001003b0 <reschedule_isr>:
1003b0: 41 57 push %r15
1003b2: 41 56 push %r14
1003b4: 41 55 push %r13
1003b6: 41 54 push %r12
1003b8: 41 53 push %r11
1003ba: 41 52 push %r10
1003bc: 41 51 push %r9
1003be: 41 50 push %r8
1003c0: 55 push %rbp
1003c1: 57 push %rdi
1003c2: 56 push %rsi
1003c3: 53 push %rbx
1003c4: 51 push %rcx
1003c5: 52 push %rdx
1003c6: 50 push %rax
1003c7: fc cld
...
1003ed: 58 pop %rax
1003ee: 5a pop %rdx
1003ef: 59 pop %rcx
1003f0: 5b pop %rbx
1003f1: 5e pop %rsi
1003f2: 5f pop %rdi
1003f3: 5d pop %rbp
1003f4: 41 58 pop %r8
1003f6: 41 59 pop %r9
1003f8: 41 5a pop %r10
1003fa: 41 5b pop %r11
1003fc: 41 5c pop %r12
1003fe: 41 5d pop %r13
100400: 41 5e pop %r14
100402: 41 5f pop %r15
100404: 48 cf iretq
100406: 66 2e 0f 1f 84 00 00 nopw %cs:0x0(%rax,%rax,1)
10040d: 00 00 00
0000000000100410 <timer_reschedule_isr>:
100410: 55 push %rbp
100411: 48 89 e5 mov %rsp,%rbp
100414: 41 57 push %r15
100416: 41 56 push %r14
100418: 41 55 push %r13
10041a: 41 54 push %r12
10041c: 41 53 push %r11
10041e: 41 52 push %r10
100420: 41 51 push %r9
100422: 41 50 push %r8
100424: 57 push %rdi
100425: 56 push %rsi
100426: 53 push %rbx
100427: 51 push %rcx
100428: 52 push %rdx
100429: 50 push %rax
10042a: 48 83 e4 f0 and $0xfffffffffffffff0,%rsp
10042e: 48 83 ec 20 sub $0x20,%rsp
100432: fc cld
....
10048b: 48 8d 65 90 lea -0x70(%rbp),%rsp
10048f: 58 pop %rax
100490: 5a pop %rdx
100491: 59 pop %rcx
100492: 5b pop %rbx
100493: 5e pop %rsi
100494: 5f pop %rdi
100495: 41 58 pop %r8
100497: 41 59 pop %r9
100499: 41 5a pop %r10
10049b: 41 5b pop %r11
10049d: 41 5c pop %r12
10049f: 41 5d pop %r13
1004a1: 41 5e pop %r14
1004a3: 41 5f pop %r15
1004a5: 5d pop %rbp
1004a6: 48 cf iretq
1004a8: 0f 1f 84 00 00 00 00 nopl 0x0(%rax,%rax,1)
1004af: 00
And if I remove rbp from both clobber lists they are still different:
00000000001003b0 <reschedule_isr>:
1003b0: 41 57 push %r15
1003b2: 41 56 push %r14
1003b4: 41 55 push %r13
1003b6: 41 54 push %r12
1003b8: 41 53 push %r11
1003ba: 41 52 push %r10
1003bc: 41 51 push %r9
1003be: 41 50 push %r8
1003c0: 57 push %rdi
1003c1: 56 push %rsi
1003c2: 53 push %rbx
1003c3: 51 push %rcx
1003c4: 52 push %rdx
1003c5: 50 push %rax
1003c6: fc cld
....
1003ec: 58 pop %rax
1003ed: 5a pop %rdx
1003ee: 59 pop %rcx
1003ef: 5b pop %rbx
1003f0: 5e pop %rsi
1003f1: 5f pop %rdi
1003f2: 41 58 pop %r8
1003f4: 41 59 pop %r9
1003f6: 41 5a pop %r10
1003f8: 41 5b pop %r11
1003fa: 41 5c pop %r12
1003fc: 41 5d pop %r13
1003fe: 41 5e pop %r14
100400: 41 5f pop %r15
100402: 48 cf iretq
100404: 66 90 xchg %ax,%ax
100406: 66 2e 0f 1f 84 00 00 nopw %cs:0x0(%rax,%rax,1)
10040d: 00 00 00
0000000000100410 <timer_reschedule_isr>:
100410: 55 push %rbp
100411: 48 89 e5 mov %rsp,%rbp
100414: 41 57 push %r15
100416: 41 56 push %r14
100418: 41 55 push %r13
10041a: 41 54 push %r12
10041c: 41 53 push %r11
10041e: 41 52 push %r10
100420: 41 51 push %r9
100422: 41 50 push %r8
100424: 57 push %rdi
100425: 56 push %rsi
100426: 53 push %rbx
100427: 51 push %rcx
100428: 52 push %rdx
100429: 50 push %rax
10042a: 48 83 e4 f0 and $0xfffffffffffffff0,%rsp
10042e: 48 83 ec 20 sub $0x20,%rsp
100432: fc cld
...
10048b: 48 8d 65 90 lea -0x70(%rbp),%rsp
10048f: 58 pop %rax
100490: 5a pop %rdx
100491: 59 pop %rcx
100492: 5b pop %rbx
100493: 5e pop %rsi
100494: 5f pop %rdi
100495: 41 58 pop %r8
100497: 41 59 pop %r9
100499: 41 5a pop %r10
10049b: 41 5b pop %r11
10049d: 41 5c pop %r12
10049f: 41 5d pop %r13
1004a1: 41 5e pop %r14
1004a3: 41 5f pop %r15
1004a5: 5d pop %rbp
1004a6: 48 cf iretq
1004a8: 0f 1f 84 00 00 00 00 nopl 0x0(%rax,%rax,1)
1004af: 00
In my opinion, even if rbp is special, it still needs to be available in the
struct full_stack_frame.
Also, isn't rsp special? Would the compiler or programmer be responsible for
initializing it. It seems to me it has to be the compiler, but could be wrong.