Interrupts in user mode
Interrupts in user mode
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?
Re: Interrupts in user mode
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/
http://github.com/Jezze/fudge/
Re: Interrupts in user mode
And why is it never called?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
Re: Interrupts in user mode
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?
- piranha
- Member
- Posts: 1391
- Joined: Thu Dec 21, 2006 7:42 pm
- Location: Unknown. Momentum is pretty certain, however.
- Contact:
Re: Interrupts in user mode
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
-JL
SeaOS: Adding VT-x, networking, and ARM support
dbittman on IRC, @danielbittman on twitter
https://dbittman.github.io
dbittman on IRC, @danielbittman on twitter
https://dbittman.github.io
Re: Interrupts in user mode
(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?
(2) Can you call syscalls from user mode? I.e. do you have a correct kernel stack and DPL in the IDT entries?
Re: Interrupts in user mode
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.
Happy hunting!
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));
Re: Interrupts in user mode
They were before I got into ring 3.(1) Are interrupts enabled?
Yeah. I can successfully make syscalls without a problem.(2) Can you call syscalls from user mode? I.e. do you have a correct kernel stack and DPL in the IDT entries?
Re: Interrupts in user mode
And what is the value of EFLAGS that's on the stack before you IRET?yoshi65 wrote:They were before I got into ring 3(1) Are interrupts enabled?
Cheers,
Adam
Re: Interrupts in user mode
My code ors the correct flag as follows from my under standing...
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.
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.
Thanks, for all of your guys' time so far. You guys are great.
Re: Interrupts in user mode
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...
Re: Interrupts in user mode
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
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!
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: \
");
}
I am so close thanks for the EFLAG suggestion hopefully this is the last hurdle.
Thanks again!
Re: Interrupts in user mode
Sorry for the double post again but an update:
I added those lines but it needs to be
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?
I added those lines but it needs to be
Code: Select all
or $0x200, %eax;
in my console so I am guessing this has to do with incorrect stack placement?
Re: Interrupts in user mode
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.
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/
http://github.com/Jezze/fudge/
Re: Interrupts in user mode
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)