Hello,
I make my student project, details under http://gladnon.wikidot.com .
So, I have a few *problems*... I want to read the registers PMBASE, SMI_EN, SMI_STS (related to System Management Mode -- SMM). Please, see attached file, this is my example program.
The mechanism (standard PCI configuration mechanism) to read/write from/to PMBASE, SMI_EN, SMI_STS is taken from: www.ssi.gouv.fr/fr/sciences/fichiers/lti/cansecwest2006-duflot-paper.pdf (site 6)
However, the example program doesnt make what I want. I probed it on my machine, chipset is ICH3M. Executed as root the output is either --- PMBASE = 0x900007 Address of SMI_EN (PMBASE + 0x30): 0x900037 Address of SMI_STS (PMBASE + 0x34): 0x90003b Saved value in SMI_EN : 0x900007 Saved value in SMI_STS: 0x900007 --- or --- PMBASE = 0x54001ff Address of SMI_EN (PMBASE + 0x30): 0x540022f Address of SMI_STS (PMBASE + 0x34): 0x5400233 Saved value in SMI_EN : 0x54001ff Saved value in SMI_STS: 0x54001ff --- or --- PMBASE = 0x60000 Address of SMI_EN (PMBASE + 0x30): 0x60030 Address of SMI_STS (PMBASE + 0x34): 0x60034 Saved value in SMI_EN : 0x60000 Saved value in SMI_STS: 0x60000 --- depending on it, if executed on normal console or xterm. Sometimes, while executing, system freezes or crashes with "Kernel panic -- not syncing: Attempted to kill the idle task!" ... Furthermore, I think, that the saved values in PMBASE, SMI_EN and SMI_STS shouldnt be the same.
So, I have two questions: 1. Did I understood correctly how this pci mechanism for accessing registers works? If not, how can I access them? 2. Why does the system crash, since I'm accessing registers only read-only (except "outl(0xCF8, address)")?
Thank you in advance!
Andon
--------------------------------- Boardwalk for $500? In 2007? Ha! Play Monopoly Here and Now (it's updated for today's economy) at Yahoo! Games.
On Mon, May 21, 2007 at 06:18:53AM -0700, Andon Tschauschev wrote:
- Did I understood correctly how this pci mechanism for accessing
registers works? If not, how can I access them?
Yes and no.
- Why does the system crash, since I'm accessing registers only
read-only (except "outl(0xCF8, address)")?
Because the operating system may also be doing PCI accesses and there may be a conflict between your program and the kernel.
Using ports cf8/cfc is one way that PCI registers can be accessed, but it is only suitable if you are certain that you will be the only process using it.
If there is an operating system running, you should use the PCI enumeration API that the operating system provides. For Linux, look at libpci and/or pciutils. The application setpci can be used to peek and poke values in PCI config space.
//Peter
Hello,
If there is an operating system running, you should use the PCI enumeration API that the operating system provides. For Linux, look at libpci and/or pciutils.
OK, 0xCFC/0xCF8 is not so suitable, this time I'm using libpci: <start code> #include <stdio.h> #include <pci/pci.h>
int main(void) {
struct pci_access *pacc; struct pci_dev *LPCBridge; u32 pmbase_value, smi_en_offset, smi_sts_offset, smi_en_value, smi_sts_value;
pacc = pci_alloc(); pci_init(pacc);
LPCBridge = pci_get_dev(pacc, 0, 0, 0x1f, 0);
pmbase_value = pci_read_long(LPCBridge, 0x40); printf("Stored value in PMBASE: 0x%08x\n", pmbase_value);
smi_en_offset = pmbase_value + 0x30; smi_sts_offset = pmbase_value + 0x34; printf("Offset to SMI_EN (PMBASE + 0x30): 0x%08x\n", smi_en_offset); printf("Offset to SMI_STS (PMBASE + 0x34): 0x%08x\n", smi_sts_offset);
smi_en_value = pci_read_long(LPCBridge, smi_en_offset); smi_sts_value = pci_read_long(LPCBridge, smi_sts_offset); printf("Value in SMI_EN: 0x%08x\n", smi_en_value); printf("Value in SMI_STS: 0x%08x\n", smi_sts_value);
return 0; } <end code>
Compiling it and executing as root generates the output: <start output> Stored value in PMBASE: 0x00000801 Offset to SMI_EN (PMBASE + 0x30): 0x00000831 Offset to SMI_STS (PMBASE + 0x34): 0x00000835 pcilib: Unaligned read: pos=831, len=4 <end output>
Chipset is ICH3M.
Any suggestions?
Regards
Andon
Peter Stuge stuge-linuxbios@cdy.org wrote: On Mon, May 21, 2007 at 06:18:53AM -0700, Andon Tschauschev wrote:
- Did I understood correctly how this pci mechanism for accessing
registers works? If not, how can I access them?
Yes and no.
- Why does the system crash, since I'm accessing registers only
read-only (except "outl(0xCF8, address)")?
Because the operating system may also be doing PCI accesses and there may be a conflict between your program and the kernel.
Using ports cf8/cfc is one way that PCI registers can be accessed, but it is only suitable if you are certain that you will be the only process using it.
If there is an operating system running, you should use the PCI enumeration API that the operating system provides. For Linux, look at libpci and/or pciutils. The application setpci can be used to peek and poke values in PCI config space.
//Peter
Au, I know, I must extract the base address from the returned value, represented by bits 15:7... Sorry.
Andon Tschauschev atschauschev@yahoo.com wrote: Hello,
If there is an operating system running, you should use the PCI enumeration API that the operating system provides. For Linux, look at libpci and/or pciutils.
OK, 0xCFC/0xCF8 is not so suitable, this time I'm using libpci: <start code> #include <stdio.h> #include <pci/pci.h>
int main(void) {
struct pci_access *pacc; struct pci_dev *LPCBridge; u32 pmbase_value, smi_en_offset, smi_sts_offset, smi_en_value, smi_sts_value;
pacc = pci_alloc(); pci_init(pacc);
LPCBridge = pci_get_dev(pacc, 0, 0, 0x1f, 0);
pmbase_value = pci_read_long(LPCBridge, 0x40); printf("Stored value in PMBASE: 0x%08x\n", pmbase_value);
smi_en_offset = pmbase_value + 0x30; smi_sts_offset = pmbase_value + 0x34; printf("Offset to SMI_EN (PMBASE + 0x30): 0x%08x\n", smi_en_offset); printf("Offset to SMI_STS (PMBASE + 0x34): 0x%08x\n", smi_sts_offset);
smi_en_value = pci_read_long(LPCBridge, smi_en_offset); smi_sts_value = pci_read_long(LPCBridge, smi_sts_offset); printf("Value in SMI_EN: 0x%08x\n", smi_en_value); printf("Value in SMI_STS: 0x%08x\n", smi_sts_value);
return 0; } <end code>
Compiling it and executing as root generates the output: <start output> Stored value in PMBASE: 0x00000801 Offset to SMI_EN (PMBASE + 0x30): 0x00000831 Offset to SMI_STS (PMBASE + 0x34): 0x00000835 pcilib: Unaligned read: pos=831, len=4 <end output>
Chipset is ICH3M.
Any suggestions?
Regards
Andon
Peter Stuge stuge-linuxbios@cdy.org wrote: On Mon, May 21, 2007 at 06:18:53AM -0700, Andon Tschauschev wrote:
- Did I understood correctly how this pci mechanism for accessing
registers works? If not, how can I access them?
Yes and no.
- Why does the system crash, since I'm accessing registers only
read-only (except "outl(0xCF8, address)")?
Because the operating system may also be doing PCI accesses and there may be a conflict between your program and the kernel.
Using ports cf8/cfc is one way that PCI registers can be accessed, but it is only suitable if you are certain that you will be the only process using it.
If there is an operating system running, you should use the PCI enumeration API that the operating system provides. For Linux, look at libpci and/or pciutils. The application setpci can be used to peek and poke values in PCI config space.
//Peter
* Andon Tschauschev atschauschev@yahoo.com [070521 20:46]:
Hello,
pmbase_value = pci_read_long(LPCBridge, 0x40);
This neads to read
pmbase_value = pci_read_long(LPCBridge, 0x40) & 0xfffffffe ;
I have not checked the data sheets but I would bet the lowest bit is enable.
Hello, pmbase_value = pci_read_long(LPCBridge, 0x40);
This neads to read
>pmbase_value = pci_read_long(LPCBridge, 0x40) & 0xfffffffe ;
I have not checked the data sheets but I would bet the lowest bit is enable.
From datasheet ICH3M, according to PMBASE:
31:16 -- reserved 15:7 -- Base address 6:1 -- reserved 0 -- Resource Indicator -- RO. tied to 1 to indicate I/O space
Should it be pmbase_value = pci_read_long(LPCBridge, 0x40) & 0xff80; ?
Is shifting necessary, too (see attached file)?
On my machine, output from my variant: Extracted address from PMBASE: 0x00000800 Offset to SMI_EN (PMBASE + 0x30): 0x00000830 Offset to SMI_STS (PMBASE + 0x34): 0x00000834 Value in SMI_EN: 0xffffffff Value in SMI_STS: 0xffffffff
Output from Stefans variant: the same as from above
Output from my variant with shift: Extracted address from PMBASE: 0x00000010 Offset to SMI_EN (PMBASE + 0x30): 0x00000040 Offset to SMI_STS (PMBASE + 0x34): 0x00000044 Value in SMI_EN: 0x00000801 Value in SMI_STS: 0x00000010
Output from Stefans variant with shift: the same as from above
Which of these four variants is correct?
Regards
Andon
--------------------------------- Building a website is a piece of cake. Yahoo! Small Business gives you all the tools to get online.
* Andon Tschauschev atschauschev@yahoo.com [070522 14:38]:
Hello, pmbase_value = pci_read_long(LPCBridge, 0x40);
This neads to read
pmbase_value = pci_read_long(LPCBridge, 0x40) & 0xfffffffe ;
I have not checked the data sheets but I would bet the lowest bit is enable.
From datasheet ICH3M, according to PMBASE: 31:16 -- reserved 15:7 -- Base address 6:1 -- reserved 0 -- Resource Indicator -- RO. tied to 1 to indicate I/O space
Should it be pmbase_value = pci_read_long(LPCBridge, 0x40) & 0xff80;
yes.
Is shifting necessary, too (see attached file)?
Does it say which bits of the base address the bits 15:7 correspond to?
I would assume no shift is required.
On Tue, May 22, 2007 at 05:38:59AM -0700, Andon Tschauschev wrote:
int main(void) {
I would just use setpci for these tricks.
//Peter
Hi Andon,
On 21.05.2007 15:18, Andon Tschauschev wrote:
I read about that project when the distributed systems group was still at the University of Tübingen. It is an interesting project but you have to be aware that the stated objectives can not be achieved completely. Even SMM interruptions will modify the behaviour of an OS because they mess with the timing. The longer you stay in the SMM handler, the more deviations from normal behaviour will happen.
Anyway, I wish you luck.
Regards, Carl-Daniel