Page 1 of 1

Integer assignment yields unexpected results in ACPICA code

Posted: Sun May 23, 2021 10:29 am
by yvrv
So i've been porting ACPICA recently and up to this moment everything was going pretty well. A few tweaks here and there, a bit of time spent reading documentation - nothing unusual. However, what i saw next made me wonder for a few days. I never encountered anything like that.

There is this perfectly normal integer assignment at tables/tbutils.c that just doesn't work. I think it's better to just show my GDB session logs.
(i use qemu+gdb as described in: https://wiki.osdev.org/Kernel_Debugging ... _with_QEMU)

Code: Select all

(gdb) set disassemble-next-line on
(gdb) set disassembly-flavor intel
(gdb) where
#0  AcpiTbParseRootTable (RsdpAddress=1006368) at acpica/tables/tbutils.c:432
#1  0xc004a83a in AcpiInitializeTables (InitialTableArray=0x0, InitialTableCount=16, AllowResize=0 '\000')
    at acpica/tables/tbxface.c:268
#2  0xc0002fbb in acpi_do_sth () at kernel/kmain.c:42
#3  0xc0003115 in kmain (mb_info=0x9500, mb_magic=732803074) at kernel/kmain.c:80
#4  0xc0002885 in start_hhalf () at kernel/start.s:41
(gdb) f
#0  AcpiTbParseRootTable (RsdpAddress=1006368) at acpica/tables/tbutils.c:432
432             Address = (ACPI_PHYSICAL_ADDRESS) Rsdp->RsdtPhysicalAddress;
=> 0xc004aaf9 <AcpiTbParseRootTable+163>:       8b 45 e0        mov    eax,DWORD PTR [ebp-0x20]
   0xc004aafc <AcpiTbParseRootTable+166>:       8b 40 10        mov    eax,DWORD PTR [eax+0x10]
(gdb) p sizeof(Address)
$1 = 8
(gdb) p sizeof(Rsdp->RsdtPhysicalAddress)
$2 = 4
(gdb) p &Address
$3 = (ACPI_PHYSICAL_ADDRESS *) 0xc003ffc8
(gdb) p &Rsdp->RsdtPhysicalAddress 
$4 = (UINT32 *) 0xc0054b30
(gdb) p Rsdp
$5 = (ACPI_TABLE_RSDP *) 0xc0054b20
(gdb) p/x Rsdp->RsdtPhysicalAddress 
$6 = 0x7fe18fe
(gdb) i r ebp
ebp            0xc003ffe0          0xc003ffe0
(gdb) i r eax
eax            0x0                 0
(gdb) si
0xc004aafc      432             Address = (ACPI_PHYSICAL_ADDRESS) Rsdp->RsdtPhysicalAddress;
   0xc004aaf9 <AcpiTbParseRootTable+163>:       8b 45 e0        mov    eax,DWORD PTR [ebp-0x20]
=> 0xc004aafc <AcpiTbParseRootTable+166>:       8b 40 10        mov    eax,DWORD PTR [eax+0x10]
(gdb) i r eax
eax            0xc0054b20          -1073394912
(gdb) si
432             Address = (ACPI_PHYSICAL_ADDRESS) Rsdp->RsdtPhysicalAddress;
=> 0xc004aaff <AcpiTbParseRootTable+169>:       89 45 e8        mov    DWORD PTR [ebp-0x18],eax
   0xc004ab02 <AcpiTbParseRootTable+172>:       c7 45 ec 00 00 00 00    mov    DWORD PTR [ebp-0x14],0x0
(gdb) i r eax
eax            0x0                 0
(gdb) si
0xc004ab02      432             Address = (ACPI_PHYSICAL_ADDRESS) Rsdp->RsdtPhysicalAddress;
   0xc004aaff <AcpiTbParseRootTable+169>:       89 45 e8        mov    DWORD PTR [ebp-0x18],eax
=> 0xc004ab02 <AcpiTbParseRootTable+172>:       c7 45 ec 00 00 00 00    mov    DWORD PTR [ebp-0x14],0x0
(gdb) si
433             TableEntrySize = ACPI_RSDT_ENTRY_SIZE;
=> 0xc004ab09 <AcpiTbParseRootTable+179>:       c7 45 f4 04 00 00 00    mov    DWORD PTR [ebp-0xc],0x4
(gdb) p/x Address 
$8 = 0x0
You can clearly see here when i start "si"-ing, the instruction that is evidently supposed to place 0x7fe18fe to eax, somehow places 0 instead.

I tried:
- using 32-bit ACPI_PHYSICAL_ADDRESS by defining ACPI_32BIT_PHYSICAL_ADDRESS
- updating my cross-compiler
- various hack combinations, like using memcpy instead
- disabling caching of virtual memory that RSDP gets mapped to
Nothing works.

Also i tried using kprintf to output values before and after assignment. It gaves the following output both on qemu and real hardware, with 32-bit or 64-bit ACPI_PHYSICAL_ADDRESS:

Code: Select all

&Rsdp->RsdtPhysicalAddress == 0xc0054b30
before assignment: Rsdp->RsdtPhysicalAddress == 0x0
after assignment: Address == 0x0; Rsdp->RsdtPhysicalAddress == 0x0
RSDP is located and verified correctly in the previous step (it uses AcpiFindRootPointer() to do so). I used kprintf() to output Rsdp->RsdtPhysicalAddress at that point and all works as expected.
RSDP memory region then gets unmapped and mapped at AcpiTbParseRootTable() again. And then it's already like that.

I have no assumptions about what might cause this and where to look for any hints. Any help would be much appreciated.
Here is the link to the file in ACPICA github repo where this assignment is located: https://github.com/acpica/acpica/blob/m ... /tbutils.c, line 432.

Re: Integer assignment yields unexpected results in ACPICA c

Posted: Sun May 23, 2021 9:15 pm
by Octocontrabass
Have you checked your segment registers?

Re: Integer assignment yields unexpected results in ACPICA c

Posted: Sun May 23, 2021 10:46 pm
by Gigasoft
TLB not flushed?

Re: Integer assignment yields unexpected results in ACPICA c

Posted: Sun May 23, 2021 11:18 pm
by yvrv
Octocontrabass wrote:Have you checked your segment registers?
Yup. My segment registers are definitely set up properly.
Gigasoft wrote:TLB not flushed?
I tried placing asm volatile("wbinvd") both before and after RSDP memory mapping. Nothing.

Re: Integer assignment yields unexpected results in ACPICA c

Posted: Sun May 23, 2021 11:21 pm
by Octocontrabass
yvrv wrote:Yup. My segment registers are definitely set up properly.
Prove it: use "info registers" in the QEMU monitor to dump them.

Re: Integer assignment yields unexpected results in ACPICA c

Posted: Sun May 23, 2021 11:25 pm
by nullplan
Is the memory accessible to any other processes in the system at that point? Could someone else be overwriting the memory? What happens if you write there using the debugger?

Re: Integer assignment yields unexpected results in ACPICA c

Posted: Wed May 26, 2021 1:03 am
by yvrv
Octocontrabass wrote: Prove it: use "info registers" in the QEMU monitor to dump them.

Code: Select all

(gdb) i r
...
cs             0x8                 8
ss             0x10                16
ds             0x10                16
es             0x10                16
fs             0x10                16
gs             0x10                16
...
(gdb) x/8xb &gdt_table[0]
0xc003e020 <gdt_table>:         0x00    0x00    0x00    0x00    0x00    0x00    0x00    0x00
(gdb) x/8xb &gdt_table[1]
0xc003e028 <gdt_table+8>:       0xff    0xff    0x00    0x00    0x00    0x9a    0xcf    0x00
(gdb) x/8xb &gdt_table[2]
0xc003e030 <gdt_table+16>:      0xff    0xff    0x00    0x00    0x00    0x93    0xcf    0x00
Here it is. It seems OK to me, but maybe there are some problems here that i can't see, who knows.
nullplan wrote: Is the memory accessible to any other processes in the system at that point? Could someone else be overwriting the memory?
No. Right now, my OS is single-processor, monotasking system. Actually, it's rather no-tasking system, since i can't execute userspace code yet.
nullplan wrote: What happens if you write there using the debugger?
Now that is an interesting suggestion. I tried placing memset(Rsdp, 0xAD, sizeof(*Rsdp)) right before all the kprintf() calls. And somehow, it magically fixed everything - Rsdp->RsdtPhysicalAddress is back to what it should have been.
However, after that, at line 444 ACPICA maps RSDT. The same problem: Table->Length is 52 in my debugger, but 0 in the actual runtime. And memset() hack doesn't work this time.
I have no idea what's happening here.

Re: Integer assignment yields unexpected results in ACPICA c

Posted: Wed May 26, 2021 1:35 am
by Gigasoft
yvrv wrote:I tried placing asm volatile("wbinvd") both before and after RSDP memory mapping. Nothing.
Wrong instruction. Use mov to cr3 to flush the entire TLB, or invlpg for individual pages.

Re: Integer assignment yields unexpected results in ACPICA c

Posted: Wed May 26, 2021 2:58 am
by 8infy
Gigasoft wrote:
yvrv wrote:I tried placing asm volatile("wbinvd") both before and after RSDP memory mapping. Nothing.
Wrong instruction. Use mov to cr3 to flush the entire TLB, or invlpg for individual pages.
> No. Right now, my OS is single-processor, monotasking system. Actually, it's rather no-tasking system, since i can't execute userspace code yet.

Unless he never calls invlpg it cannot be a problem.

Re: Integer assignment yields unexpected results in ACPICA c

Posted: Wed May 26, 2021 7:33 am
by yvrv
Gigasoft wrote:Wrong instruction. Use mov to cr3 to flush the entire TLB, or invlpg for individual pages.
8infy wrote:Unless he never calls invlpg it cannot be a problem.
Yeah. Turns out i didn't know i should use invlpg in munmap() function. Now that i do, everything works as expected. Thank you, 8infy, Gigasoft, and other kind gentlemen who have spent their time helping me.

Now excuse me as i go read intel's manual on TLB.