Bochs working, Qemu not anymore

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.
FlashBurn
Member
Member
Posts: 313
Joined: Fri Oct 20, 2006 10:14 am

Bochs working, Qemu not anymore

Post by FlashBurn »

Before you ask, at the moment I do not have the possibility to test my code on a real pc.

I have the problem that my irq code isn´t called in qemu although it is called in bochs and some other other code of me is working.

1st this is my code:

Code: Select all

#define PIC_MASTER_PORT 0x20
#define PIC_SLAVE_PORT 0xa0

#define PIC_ICW1 0x11
#define PIC_ICW2_MASTER 0x20
#define PIC_ICW2_SLAVE 0x28
#define PIC_ICW3_MASTER 0x04
#define PIC_ICW3_SLAVE 0x02
#define PIC_ICW4 0x01

void picInit() {
	//init the pic
	outb(PIC_MASTER_PORT,PIC_ICW1);
	outb(PIC_SLAVE_PORT,PIC_ICW1);
	outb(PIC_MASTER_PORT+1,PIC_ICW2_MASTER);
	outb(PIC_SLAVE_PORT+1,PIC_ICW2_SLAVE);
	outb(PIC_MASTER_PORT+1,PIC_ICW3_MASTER);
	outb(PIC_SLAVE_PORT+1,PIC_ICW3_SLAVE);
	outb(PIC_MASTER_PORT+1,PIC_ICW4);
	outb(PIC_SLAVE_PORT+1,PIC_ICW4);
	//mask all  the irqs
	outb(PIC_MASTER_PORT+1,0xff);
	outb(PIC_SLAVE_PORT+1,0xff);
}

void picUnMask(uint8t irq) {
	uint8t res;
	
	if(irq < 8) {
		res= inb(PIC_MASTER_PORT+1);
		outb(PIC_MASTER_PORT+1,res & ~(1 << irq));
	} else {
		res= inb(PIC_SLAVE_PORT+1);
		outb(PIC_SLAVE_PORT+1,res & ~(1 << (irq - 8)));
	}
}

void idtSetInt(uint32t interupt, void *base, uint8t sel, uint8t flags) {
	struct idt_entry_t *idtEntry= (struct idt_entry_t *)(IDT_ADDR + (interupt << 3));
	
	idtEntry->baseLo= (uint16t)((uint32t)base & 0xffff);
	idtEntry->sel= sel;
	idtEntry->flags= flags;
	idtEntry->baseHi= (uint16t)((uint32t)base >> 16);
}

void kbdInit() {
	idtSetInt(0x21,kbdIRQidt,8,0x8e);
	picUnMask(1);
}
This is my irq handler code:

Code: Select all

kbdIRQidt:
	pushad
	
;	call kbdIRQFunc

	add byte[0xb8002],1
	
	in al,0x60
	
	mov al,0x20
	out 0x20,al
	
	popad
	iret
So, as I said,in Bochs this code is working, but not in Qemu and all other os´s are working,so it is no problem of my qemu. also an older os of mine is working and it uses similar code.

Is there something I miss?

Edit::

First I call "picInit()", then "kbdInit()" and then I enable ints.
User avatar
01000101
Member
Member
Posts: 1599
Joined: Fri Jun 22, 2007 12:47 pm
Contact:

Re: Bochs working, Qemu not anymore

Post by 01000101 »

Do you ever load your IDT (using LIDT)? If so, can we see that code? Also, do you get any debugging info from QEMU when it TFs?

[edit] also, iirc, the main difference between the two emulators is that BOCHS zeros memory on load while QEMU doesn't. Thus, if you have an uninitialized variable/array, in BOCHS it will be NULL, but it will be undefined in QEMU and you could use garbage values. [/edit]
FlashBurn
Member
Member
Posts: 313
Joined: Fri Oct 20, 2006 10:14 am

Re: Bochs working, Qemu not anymore

Post by FlashBurn »

Ok, here is my idt init code:

Code: Select all

static inline void zeromem4b(void *dst, uint32t count) {
	asm volatile("xor %%eax,%%eax\n\trep stosl"
		:
		:"c"(count),"D"(dst));
}

static inline void load_idtr(struct idtr_t *idtr) {
	asm volatile("lidt %[input]"
		:
		:[input] "m"(*idtr));
}

//zero the mem of the idt
	zeromem4b((void *)IDT_ADDR,IDT_LIMIT >> 2);
	//init the idtr and load it
	idtr.base= IDT_ADDR;
	idtr.limit= IDT_LIMIT;
	load_idtr(&idtr);
I checked in Qemu that my idt has the right values and that it got loaded. Also qemu is telling me that 2 ints (0 and 1) are requested, but the code don´t get called.
FlashBurn
Member
Member
Posts: 313
Joined: Fri Oct 20, 2006 10:14 am

Re: Bochs working, Qemu not anymore

Post by FlashBurn »

Ok, it seems to be a problem with zeroing memory! LD doesn´t give me the right adresses :?:

This is my linker script:

Code: Select all

OUTPUT_FORMAT("binary")
ENTRY(loader_stub)

SECTIONS
{
	. = 0x10000;
	_text_start = .;
	.text : { *(.text) }
	. = ALIGN(16);
	_data_start = .;
	.data : { *(.data) }
	. = ALIGN(16);
	_bss_start = .;
	.bss : { *(.bss) }
	. = ALIGN(16);
	_loader_end = .;
}
These are the relevant lines of my code:

Code: Select all

extern void _text_start, _data_start, _bss_start, _loader_end;

zeromem4b((uint32t *)&_data_start,(&_loader_end - &_data_start) >> 2);

printf("data start: %#X, ",&_data_start);
printf("bss start: %#X, ",&_bss_start);
printf("loader end: %#X\n",&_loader_end);
printf("loaderArgs: %#X\n",&loaderArgs);
The problem are the adresses of the labels I define in the linker script. If I call zeromem4b the adress of _data_start is equal to the adress of _loader_end and _bss_start is somewhere before the two. If I don´t call zeromem4b the adress of _data_start is 0x20 bytes before _bss_start and _loader_end seems to be the right adress it should be. And this is the problem I can´t zero the mem. Does anyone knows what this could be?
quok
Member
Member
Posts: 490
Joined: Wed Oct 18, 2006 10:43 pm
Location: Kansas City, KS, USA

Re: Bochs working, Qemu not anymore

Post by quok »

You shouldn't zero the .data section. It contains initialized variables. You're overwriting important things. :)

You should only be zeroing your .bss section, which contains uninitialized data.
FlashBurn
Member
Member
Posts: 313
Joined: Fri Oct 20, 2006 10:14 am

Re: Bochs working, Qemu not anymore

Post by FlashBurn »

Yeah, I know, but as I´ve written, the problem is that the adresses aren´t right if I call my zeromem4b function.

Ok, here we go.

I called zeromem4b(&_bss_start,(&_loader_end - &_bss_start) >> 2).

Code: Select all

data start: 0x14DE0
bss start: 0x14F60
loader end: 0x14F60
loaderArgs: 0x14E00
And I didn´t call zeromem4b.

Code: Select all

data start: 0x14DC0
bss start: 0x14DE0
loader end: 0x14F40
loaderArgs: 0x14DE0
"loaderArgs" is a variable and seems to be the first in the bss section.
FlashBurn
Member
Member
Posts: 313
Joined: Fri Oct 20, 2006 10:14 am

Re: Bochs working, Qemu not anymore

Post by FlashBurn »

Ok, I´ve solved the problem above, it was my zeromem4b function. I have to use the clobbered register option and then it would work if I would get this working.

The following code:

Code: Select all

	asm volatile("xor %%eax,%%eax\n\trep stosl"
		:
		:"c"(count),"D"(dst));
		:"%eax", "%ecx", "%edi");
gives me the error "can't find a register in class 'CREG' while r eloading 'asm'"???

And the problem that the irqs not working drives me crazy. I can call the pit irq handler manualy (asm ("int $0x20")), but it doesn´t work automatic. The funny thing is that it has nothing to do with code size or data size. It is only 1 line where I change a value in the data segment which decides if the code is working or not, but this value has nothing to do with the pit!!??
User avatar
01000101
Member
Member
Posts: 1599
Joined: Fri Jun 22, 2007 12:47 pm
Contact:

Re: Bochs working, Qemu not anymore

Post by 01000101 »

for the assembly problem, the clobber list should not use the "%" prefix on register names.
FlashBurn
Member
Member
Posts: 313
Joined: Fri Oct 20, 2006 10:14 am

Re: Bochs working, Qemu not anymore

Post by FlashBurn »

That´s not right, because there I get the same error, but if I use a reg which isn´t in input or output list, then it works. The problem is that I have to tell gcc that edi and so on are changed, because gcc wont recognize this and then the code isn´t working.

And I come closer to my problem with the pit :)
FlashBurn
Member
Member
Posts: 313
Joined: Fri Oct 20, 2006 10:14 am

Re: Bochs working, Qemu not anymore

Post by FlashBurn »

Ok, I solved the problem with the pit. It is some crazy thing, but the NMI is connected to one of the 2 LINT pins of the apic and if I mask or change something at the LINT1 reg of the apic, qemu wont respond to irqs (maybe also it hangs, I don´t know).

So now I have to get this inline assembly to work!

I don´t know if it would be better to try to get someone of gcc to look at it!?
pcmattman
Member
Member
Posts: 2566
Joined: Sun Jan 14, 2007 9:15 pm
Libera.chat IRC: miselin
Location: Sydney, Australia (I come from a land down under!)
Contact:

Re: Bochs working, Qemu not anymore

Post by pcmattman »

I can't remember and I haven't checked the manual (bad), but I'd suggest using "a", "c", "D" rather than "eax", "ecx" and "edi" in the clobber list.
quok
Member
Member
Posts: 490
Joined: Wed Oct 18, 2006 10:43 pm
Location: Kansas City, KS, USA

Re: Bochs working, Qemu not anymore

Post by quok »

01000101 wrote:for the assembly problem, the clobber list should not use the "%" prefix on register names.
Sorry Mr. E, you're incorrect here. The clobber list MUST use the % prefix on register names. Here's a useful doc on inline assembly: http://www.delorie.com/djgpp/doc/brenna ... djgpp.html

Let's look at the code again:

Code: Select all

asm volatile("xor %%eax,%%eax\n\trep stosl"
    :
    :"c"(count),"D"(dst));
    :"%eax", "%ecx", "%edi");
I see a couple of things here. First, there's an extra ); on the line of inputs. I'm betting that's just a typo in your code in the post and not what you really have, or you'd be getting a different error than you are from GCC.

Secondly, your inputs are ecx (c) and edi (D). GCC knows it is clobbering them (since they are inputs), so there's no need to specify them in your clobber list. Taking %ecx out of the clobber list (but leaving %edi) will change your warning to: error: can't find a register in class 'DIREG' while reloading 'asm'.
So get rid of both %ecx and %edx from your clobber list.

Next, remember how the 'rep' instruction works. Your code is going to repeat until ecx contains the value zero. That alters condition bits in EFLAGS, which GCC may need to know about, so you should include 'cc' in the clobbers list. This may not strictly be needed, but it's probably a good idea to include it.

Finally, you'll probably want to include 'cld' before 'rep stosl' to make sure that %edi gets incremented rather than accidentally decremented.

You can optionally change the clobbers from "%eax", "cc" to "cc", "memory" and get somewhat the same effect. The "memory" clobber tells GCC that you wrote to a variable that may be in a register, and effectively clobbers all the registers.

Thinking about it, since you do have zeromem4b as an inline function, the proper clobbers are most likely "cc", "memory". But give "%eax", "cc" a try as well and let us know which works. :)
User avatar
01000101
Member
Member
Posts: 1599
Joined: Fri Jun 22, 2007 12:47 pm
Contact:

Re: Bochs working, Qemu not anymore

Post by 01000101 »

wow, guess so.
I didn't have the answer off the top of my head so I went to http://www.ibiblio.org/gferg/ldp/GCC-In ... html#ss5.3 to get a referesher.
FlashBurn
Member
Member
Posts: 313
Joined: Fri Oct 20, 2006 10:14 am

Re: Bochs working, Qemu not anymore

Post by FlashBurn »

Yes, I have a typo in my posted code, because I made copy and paste and commented the code out.

As I said, gcc doesn´t know that edi is clobbered, because it uses edi after this code as if it didn´t change! I had a look at the assembly code to prove that.

Also I don´t need "cld", because I think since gcc 4.0 you can be sure that gcc wont change that flag.
pcmattman
Member
Member
Posts: 2566
Joined: Sun Jan 14, 2007 9:15 pm
Libera.chat IRC: miselin
Location: Sydney, Australia (I come from a land down under!)
Contact:

Re: Bochs working, Qemu not anymore

Post by pcmattman »

Also I don´t need "cld", because I think since gcc 4.0 you can be sure that gcc wont change that flag.
The point is, that unless the direction flag is cleared it'll decrement by default. That's why you should have cld in your assembly.
Post Reply