Invlpg operand errors.

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.
Post Reply
TylerH
Member
Member
Posts: 285
Joined: Tue Apr 13, 2010 8:00 pm
Contact:

Invlpg operand errors.

Post by TylerH »

I can't get GCC (or, more correctly, GAS) to take my inline invlpg. When I cast the address (which I store as a uintptr_t) to a void* and try to dereference it, I get "‘void*’ is not a pointer-to-object type." When I cast to it anything else (char, short, int, long long), I get "operand size mismatch for `invlpg.'"

Is this a GCC/GAS bug, or am I doing something wrong?

Code: Select all

void page_table::map(uintptr_t virtual_address, uintptr_t physical_address, ptrdiff_t size, bool user, bool writable)
{
	for(ptrdiff_t i = 0;i + PGSIZE <= size;i += PGSIZE)
	{
		auto &pte = _page_table[PTX(virtual_address + i)];
		pte.set_page(physical_address + i);
		pte.set_present(true);
		pte.user(user);
		pte.writable(writable);
		
		asm volatile("invlpg %0" :: "m"(*((type*)virtual_address + i)));
	}
}
What should "type" be?
TylerH
Member
Member
Posts: 285
Joined: Tue Apr 13, 2010 8:00 pm
Contact:

Re: Invlpg operand errors.

Post by TylerH »

Wouldn't that result in the page containing virtual_address being flushed from the TLB, not the page it points to? There's a warning about that specific problem here: http://wiki.osdev.org/Inline_Assembly/E ... PGFLUSHTLB.
TylerH
Member
Member
Posts: 285
Joined: Tue Apr 13, 2010 8:00 pm
Contact:

Re: Invlpg operand errors.

Post by TylerH »

Even reinterpret_cast doesn't work for me. I get the same error as trying to C-style cast it to char*, "Assembler messages: Error: operand size mismatch for `invlpg.'"

I compiled the code above to assembly (with -masm=intel) and the code in question is output as: "invlpg BYTE PTR [eax]."

gcc -v

Code: Select all

$i686-elf-gcc -v
Using built-in specs.
COLLECT_GCC=i686-elf-gcc
COLLECT_LTO_WRAPPER=/usr/local/libexec/gcc/i686-elf/4.6.2/lto-wrapper
Target: i686-elf
Configured with: ../gcc-4.6.2/configure --prefix=/usr/local/ --target=i686-elf --enable-languages=c,c++ --with-newlib --enable-lto
Thread model: single
gcc version 4.6.2 (GCC)
TylerH
Member
Member
Posts: 285
Joined: Tue Apr 13, 2010 8:00 pm
Contact:

Re: Invlpg operand errors.

Post by TylerH »

It is a bug. I had been compiling with -masm=intel all the time, so I could use intel syntax in my inline assembly. I tried compiling without -masm=intel and it worked.
TylerH
Member
Member
Posts: 285
Joined: Tue Apr 13, 2010 8:00 pm
Contact:

Re: Invlpg operand errors.

Post by TylerH »

A workaround that allows -masm=intel to be used is to require va to be put into a general purpose register (using "r") and then dereferencing that register.

Code: Select all

int main()
{
    uintptr_t va = 0;
    int i = 1;
    asm volatile("invlpg [%0]" :: "r"(va+i));
}
Post Reply