Interrupts in user mode

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
yoshi65
Posts: 11
Joined: Sun Mar 11, 2012 8:49 pm

Interrupts in user mode

Post by yoshi65 »

Okay guys I have followed the tutorial at http://www.jamesmolloy.co.uk/ and at the last tutorial I can't do anything with interrupts. I have a get_ticks function that is supposed to get the number of ticks that have passed and they all return 2 because the interrupt is never called, I would like to get this working so I can use the keyboard. Can anyone help me?
User avatar
Jezze
Member
Member
Posts: 395
Joined: Thu Jul 26, 2007 1:53 am
Libera.chat IRC: jfu
Contact:

Re: Interrupts in user mode

Post by Jezze »

How can we help when you provide no code or anything other than "it does not work"?
Fudge - Simplicity, clarity and speed.
http://github.com/Jezze/fudge/
User avatar
VolTeK
Member
Member
Posts: 815
Joined: Sat Nov 15, 2008 2:37 pm
Location: The Fire Nation

Re: Interrupts in user mode

Post by VolTeK »

yoshi65 wrote: I have a get_ticks function that is supposed to get the number of ticks that have passed and they all return 2 because the interrupt is never called
And why is it never called?
yoshi65
Posts: 11
Joined: Sun Mar 11, 2012 8:49 pm

Re: Interrupts in user mode

Post by yoshi65 »

Sorry guys for the lack of code. I don't have it with me right now but all I know is that in user mode I cannot receive any interrupts. Why does entering user mode get rid of the interrupts?
User avatar
piranha
Member
Member
Posts: 1391
Joined: Thu Dec 21, 2006 7:42 pm
Location: Unknown. Momentum is pretty certain, however.
Contact:

Re: Interrupts in user mode

Post by piranha »

Do you receive interrupts before you switch to ring 3? Have you enabled interrupts in the switch to user mode function? Have you triple checked your code?

-JL
SeaOS: Adding VT-x, networking, and ARM support
dbittman on IRC, @danielbittman on twitter
https://dbittman.github.io
User avatar
JamesM
Member
Member
Posts: 2935
Joined: Tue Jul 10, 2007 5:27 am
Location: York, United Kingdom
Contact:

Re: Interrupts in user mode

Post by JamesM »

(1) Are interrupts enabled?
(2) Can you call syscalls from user mode? I.e. do you have a correct kernel stack and DPL in the IDT entries?
User avatar
turdus
Member
Member
Posts: 496
Joined: Tue Feb 08, 2011 1:58 pm

Re: Interrupts in user mode

Post by turdus »

Use my patch to bochs 2.5.1, it will help you tracking down the bug.
It suppresses the first debugger prompt if called with -q, otherwise it will show you helpful messages, also in debugger you'll be able to see dpls for gdt and idt. Also note that if you enable trace, it will show you whenever an interrupt is called.

Code: Select all

diff -r bochs-2.5.1/bx_debug/dbg_main.cc bochs-2.5.1new/bx_debug/dbg_main.cc
300a301
> int firstcommand=1;
327a329,333
>     if (firstcommand && SIM->get_param_enum(BXPN_BOCHS_START)->get()==BX_QUICK_START) {
>       firstcommand=0;
>       strcat(tmp_buf, "c\n");
>       charptr_ret = &tmp_buf[0];
>     } else {
336a343
>     }
2855c2862
<       dbg_printf("Code segment, base=0x%08x, limit=0x%08x, %s%s%s, %d-bit\n",
---
>       dbg_printf("Code segment, base=0x%08x, limit=0x%08x, %s%s%s, %d-bit, dpl=%d\n",
2860c2867
<         d_b ? 32 : 16);
---
>         d_b ? 32 : 16, dpl);
2862c2869
<       dbg_printf("Data segment, base=0x%08x, limit=0x%08x, %s%s%s\n",
---
>       dbg_printf("Data segment, base=0x%08x, limit=0x%08x, %s%s%s, dpl=%d\n",
2866c2873
<         (type&1)? ", Accessed" : "");
---
>         (type&1)? ", Accessed" : "", dpl);
2892c2899
<       dbg_printf("descriptor hi=0x%08x, lo=0x%08x", hi, lo);
---
>       dbg_printf("descriptor hi=0x%08x, lo=0x%08x, dpl=%d", hi, lo, dpl);
diff -r bochs-2.5.1/cpu/access.cc bochs-2.5.1new/cpu/access.cc
43c43
<     BX_DEBUG(("write_virtual_checks(): segment descriptor not valid"));
---
>     BX_DEBUG(("write_virtual_checks(): segment %d descriptor not valid", seg->selector.index));
48c48
<     BX_ERROR(("write_virtual_checks(): segment not present"));
---
>     BX_ERROR(("write_virtual_checks(): segment %d not present", seg->selector.index));
59c59
<       BX_ERROR(("write_virtual_checks(): no write access to seg"));
---
>       BX_ERROR(("write_virtual_checks(): no write access to seg %d", seg->selector.index));
66c66
<         BX_ERROR(("write_virtual_checks(): write beyond limit, r/w"));
---
>         BX_ERROR(("write_virtual_checks(): write beyond limit, r/w, seg %d", seg->selector.index));
89c89
<         BX_ERROR(("write_virtual_checks(): write beyond limit, r/w ED"));
---
>         BX_ERROR(("write_virtual_checks(): write beyond limit, r/w ED, seg %d", seg->selector.index));
95c95
<       BX_PANIC(("write_virtual_checks(): unknown descriptor type=%d", seg->cache.type));
---
>       BX_PANIC(("write_virtual_checks(): unknown descriptor type=%d seg %d", seg->cache.type, seg->selector.index));
107c107
<     BX_DEBUG(("read_virtual_checks(): segment descriptor not valid"));
---
>     BX_DEBUG(("read_virtual_checks(): segment %d descriptor not valid", seg->selector.index));
112c112
<     BX_ERROR(("read_virtual_checks(): segment not present"));
---
>     BX_ERROR(("read_virtual_checks(): segment %d not present", seg->selector.index));
124c124
<         BX_ERROR(("read_virtual_checks(): read beyond limit"));
---
>         BX_ERROR(("read_virtual_checks(): read beyond limit seg %d", seg->selector.index));
143c143
<         BX_ERROR(("read_virtual_checks(): read beyond limit ED"));
---
>         BX_ERROR(("read_virtual_checks(): read beyond limit ED seg %d", seg->selector.index));
155c155
<       BX_PANIC(("read_virtual_checks(): unknown descriptor type=%d", seg->cache.type));
---
>       BX_PANIC(("read_virtual_checks(): unknown descriptor type=%d seg %d", seg->cache.type, seg->selector.index));
167c167
<     BX_DEBUG(("execute_virtual_checks(): segment descriptor not valid"));
---
>     BX_DEBUG(("execute_virtual_checks(): segment %d descriptor not valid", seg->selector.index));
172c172
<     BX_ERROR(("execute_virtual_checks(): segment not present"));
---
>     BX_ERROR(("execute_virtual_checks(): segment %d not present", seg->selector.index));
184c184
<         BX_ERROR(("execute_virtual_checks(): read beyond limit"));
---
>         BX_ERROR(("execute_virtual_checks(): read beyond limit seg %d", seg->selector.index));
199c199
<         BX_ERROR(("execute_virtual_checks(): read beyond limit execute only"));
---
>         BX_ERROR(("execute_virtual_checks(): read beyond limit execute only seg %d", seg->selector.index));
213c213
<         BX_ERROR(("execute_virtual_checks(): read beyond limit ED"));
---
>         BX_ERROR(("execute_virtual_checks(): read beyond limit ED seg %d", seg->selector.index));
219c219
<       BX_PANIC(("execute_virtual_checks(): unknown descriptor type=%d", seg->cache.type));
---
>       BX_PANIC(("execute_virtual_checks(): unknown descriptor type=%d seg %d", seg->cache.type, seg->selector.index));
234c234
<     BX_PANIC(("undefined segment passed to strseg()!"));
---
>     BX_PANIC(("undefined segment %d passed to strseg()!", seg->selector.index));
268c268
<     BX_ERROR(("system_read_byte(): canonical failure"));
---
>     BX_ERROR(("system_read_byte(): canonical failure %lx", laddr));
298c298
<     BX_ERROR(("system_read_word(): canonical failure"));
---
>     BX_ERROR(("system_read_word(): canonical failure %lx", laddr));
328c328
<     BX_ERROR(("system_read_dword(): canonical failure"));
---
>     BX_ERROR(("system_read_dword(): canonical failure %lx", laddr));
358c358
<     BX_ERROR(("system_read_qword(): canonical failure"));
---
>     BX_ERROR(("system_read_qword(): canonical failure %lx", laddr));
391c391
<     BX_ERROR(("system_write_byte(): canonical failure"));
---
>     BX_ERROR(("system_write_byte(): canonical failure %lx", laddr));
423c423
<     BX_ERROR(("system_write_word(): canonical failure"));
---
>     BX_ERROR(("system_write_word(): canonical failure %lx", laddr));
455c455
<     BX_ERROR(("system_write_dword(): canonical failure"));
---
>     BX_ERROR(("system_write_dword(): canonical failure %lx", laddr));
diff -r bochs-2.5.1/cpu/ctrl_xfer_pro.cc bochs-2.5.1new/cpu/ctrl_xfer_pro.cc
138c138
<       BX_ERROR(("branch_far64: canonical RIP violation"));
---
>       BX_ERROR(("branch_far64: canonical RIP violation %lx", rip));
149c149
<       BX_ERROR(("branch_far64: RIP > limit"));
---
>       BX_ERROR(("branch_far64: RIP(%lx) > limit(%lx)", rip, descriptor->u.segment.limit_scaled));
diff -r bochs-2.5.1/cpu/exception.cc bochs-2.5.1new/cpu/exception.cc
46c46
<     BX_ERROR(("interrupt(long mode): vector must be within IDT table limits, IDT.limit = 0x%x", BX_CPU_THIS_PTR idtr.limit));
---
>     BX_ERROR(("interrupt(long mode): vector %d must be within IDT table limits, IDT.limit = 0x%x", vector, BX_CPU_THIS_PTR idtr.limit));
54c54
<     BX_ERROR(("interrupt(long mode): IDT entry extended attributes DWORD4 TYPE != 0"));
---
>     BX_ERROR(("interrupt(long mode): IDT entry %d extended attributes DWORD4 TYPE != 0", vector));
66c66
<     BX_ERROR(("interrupt(long mode): gate descriptor is not valid sys seg"));
---
>     BX_ERROR(("interrupt(long mode): gate descriptor %d is not valid sys seg", vector));
75,76c75,76
<     BX_ERROR(("interrupt(long mode): unsupported gate type %u",
<         (unsigned) gate_descriptor.type));
---
>     BX_ERROR(("interrupt(long mode): unsupported gate type %u vector %d",
>         (unsigned) gate_descriptor.type, vector));
84c84
<     BX_ERROR(("interrupt(long mode): soft_int && gate.dpl < CPL"));
---
>     BX_ERROR(("interrupt(long mode): soft_int(%d) && gate.dpl(%d) < CPL(%d)", vector, gate_descriptor.dpl, CPL));
103c103
<     BX_ERROR(("int_trap_gate(long mode): selector null"));
---
>     BX_ERROR(("int_trap_gate(long mode): selector null vector %d",vector));
120c120
<     BX_ERROR(("interrupt(long mode): not accessible or not code segment"));
---
>     BX_ERROR(("interrupt(long mode): not accessible or not code segment vector %d", vector));
127c127
<     BX_ERROR(("interrupt(long mode): must be 64 bit segment"));
---
>     BX_ERROR(("interrupt(long mode): must be 64 bit segment vector %d", vector));
133c133
<     BX_ERROR(("interrupt(long mode): segment not present"));
---
>     BX_ERROR(("interrupt(long mode): segment not present vector %d", vector));
253c253
<     BX_ERROR(("interrupt(): vector must be within IDT table limits, IDT.limit = 0x%x", BX_CPU_THIS_PTR idtr.limit));
---
>     BX_ERROR(("interrupt(): vector %d must be within IDT table limits, IDT.limit = 0x%x", vector, BX_CPU_THIS_PTR idtr.limit));
279,280c279,280
<     BX_ERROR(("interrupt(): gate.type(%u) != {5,6,7,14,15}",
<       (unsigned) gate_descriptor.type));
---
>     BX_ERROR(("interrupt(): gate.type(%u) != {5,6,7,14,15} vector %d",
>       (unsigned) gate_descriptor.type, vector));
287c287
<     BX_ERROR(("interrupt(): soft_int && (gate.dpl < CPL)"));
---
>     BX_ERROR(("interrupt(): soft_int(%d) && (gate.dpl(%d) < CPL(%d))", vector, gate_descriptor.dpl, CPL));
293c293
<     BX_ERROR(("interrupt(): gate not present"));
---
>     BX_ERROR(("interrupt(): gate not present vector %d", vector));
306c306
<       BX_ERROR(("interrupt(): tss_selector.ti=1 from gate descriptor - #GP(tss_selector)"));
---
>       BX_ERROR(("interrupt(): tss_selector.ti=1 from gate descriptor - #GP(tss_selector) vector %d",vector));
318c318
<       BX_ERROR(("interrupt(): TSS selector points to invalid or bad TSS - #GP(tss_selector)"));
---
>       BX_ERROR(("interrupt(): TSS selector points to invalid or bad TSS - #GP(tss_selector) vector %d seg %d", vector, tss_selector.index));
325c325
<       BX_ERROR(("interrupt(): TSS selector points to bad TSS - #GP(tss_selector)"));
---
>       BX_ERROR(("interrupt(): TSS selector points to bad TSS - #GP(tss_selector) vector %d seg %d", vector, tss_selector.index));
331c331
<       BX_ERROR(("interrupt(): TSS descriptor.p == 0"));
---
>       BX_ERROR(("interrupt(): TSS descriptor.p == 0 vector %d seg", vector, tss_selector.index));
354c354
<       BX_ERROR(("interrupt(): EIP > CS.limit"));
---
>       BX_ERROR(("interrupt(): EIP(%x) > CS.limit(%x)",EIP,BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.limit_scaled));
437c437
<         BX_ERROR(("interrupt(): SS.rpl != CS.dpl"));
---
>         BX_ERROR(("interrupt(): SS.rpl(%d) != CS.dpl(%d)", ss_selector.rpl, cs_descriptor.dpl));
444c444
<         BX_ERROR(("interrupt(): SS.dpl != CS.dpl"));
---
>         BX_ERROR(("interrupt(): SS.dpl(%d) != CS.dpl(%d)", ss_descriptor.dpl, cs_descriptor.dpl));
diff -r bochs-2.5.1/cpu/segment_ctrl_pro.cc bochs-2.5.1new/cpu/segment_ctrl_pro.cc
56c56
<         BX_ERROR(("load_seg_reg(SS): rpl != CPL"));
---
>         BX_ERROR(("load_seg_reg(SS): rpl(%d) != CPL(%d)", ss_selector.rpl, CPL));
77c77
<         BX_ERROR(("load_seg_reg(SS): dpl != CPL"));
---
>         BX_ERROR(("load_seg_reg(SS): dpl(%d) != CPL(%d)", descriptor.dpl, CPL));
134c134
<           BX_ERROR(("load_seg_reg(%s, 0x%04x): RPL & CPL must be <= DPL", strseg(seg), new_value));
---
>           BX_ERROR(("load_seg_reg(%s, 0x%04x): RPL(%d) & CPL(%d) must be <= DPL(%d)", strseg(seg), new_value, selector.rpl, CPL, descriptor.dpl));

Happy hunting!
yoshi65
Posts: 11
Joined: Sun Mar 11, 2012 8:49 pm

Re: Interrupts in user mode

Post by yoshi65 »

(1) Are interrupts enabled?
They were before I got into ring 3.
(2) Can you call syscalls from user mode? I.e. do you have a correct kernel stack and DPL in the IDT entries?
Yeah. I can successfully make syscalls without a problem.
User avatar
AJ
Member
Member
Posts: 2646
Joined: Sun Oct 22, 2006 7:01 am
Location: Devon, UK
Contact:

Re: Interrupts in user mode

Post by AJ »

yoshi65 wrote:
(1) Are interrupts enabled?
They were before I got into ring 3
And what is the value of EFLAGS that's on the stack before you IRET?

Cheers,
Adam
yoshi65
Posts: 11
Joined: Sun Mar 11, 2012 8:49 pm

Re: Interrupts in user mode

Post by yoshi65 »

My code ors the correct flag as follows from my under standing...

Code: Select all

pop %eax ; Get EFLAGS back into EAX. The only way to read EFLAGS is to pushf then pop.
or %eax, $0x200 ; Set the IF flag.
push %eax ; Push the new EFLAGS value back onto the stack.
My code is pretty much exactly the same as what is on the website mentioned accept I have a system function that returns the "ticks" variable from the timer.

Thanks, for all of your guys' time so far. You guys are great.
User avatar
Nessphoro
Member
Member
Posts: 308
Joined: Sat Apr 30, 2011 12:50 am

Re: Interrupts in user mode

Post by Nessphoro »

yoshi65 wrote:Yeah. I can successfully make syscalls without a problem.
yoshi65 wrote:...I have a system function that returns the "ticks" variable from the timer...
yoshi65
Posts: 11
Joined: Sun Mar 11, 2012 8:49 pm

Re: Interrupts in user mode

Post by yoshi65 »

Hey again,
Sorry for the double post but apparently that last code segment wasn't in
the tutorials code but just in the tutorial. So I inserted it in

Code: Select all

void switch_to_user_mode()
{
   // Set up a stack structure for switching to user mode.
   asm volatile("  \ 
     cli; \ 
     mov $0x23, %ax; \ 
     mov %ax, %ds; \ 
     mov %ax, %es; \ 
     mov %ax, %fs; \ 
     mov %ax, %gs; \ 
                   \ 
     mov %esp, %eax; \ 
     pushl $0x23; \ 
     pushl %eax; \ 
     pushf; \ 
     pushl $0x1B; \ 
     push $1f; \ 
     iret; \ 
   1: \ 
     ");
}
After the "pushf" like it said but my compiler gives me in invalid operand error upon compilation.
I am so close thanks for the EFLAG suggestion hopefully this is the last hurdle.

Thanks again!
yoshi65
Posts: 11
Joined: Sun Mar 11, 2012 8:49 pm

Re: Interrupts in user mode

Post by yoshi65 »

Sorry for the double post again but an update:

I added those lines but it needs to be

Code: Select all

or $0x200, %eax;
instead but now when I try to call a system function it says "Un handled interrupt 13"
in my console so I am guessing this has to do with incorrect stack placement?
User avatar
Jezze
Member
Member
Posts: 395
Joined: Thu Jul 26, 2007 1:53 am
Libera.chat IRC: jfu
Contact:

Re: Interrupts in user mode

Post by Jezze »

Verify:

1, All your pages you are using have the usermode and present bit set.
2, You have set up the tss with the esp0 correctly.
3, The idt entry for the system call you are trying to use also has the usermode bit set.
Fudge - Simplicity, clarity and speed.
http://github.com/Jezze/fudge/
yoshi65
Posts: 11
Joined: Sun Mar 11, 2012 8:49 pm

Re: Interrupts in user mode

Post by yoshi65 »

Thanks, that brings me to my next thing I found. When the TSS is installed there is a 0x0 for the esp0 entry. How can I get the stack for the kernel to put it in there? (That is assuming that is what I need to do anyway)
Post Reply