http://wiki.osdev.org/IOAPIC
http://wiki.osdev.org/APIC
These two URLs provides detailed the explanation about IOAPIC, but the read/write code do not work on my CentOS machine. The IO APIC base is 0xfec00000 on my machine (index 0xfec00000; port 0xfec00010). It is a memory maped IO memory.
I use the code in both user-level program and a kernel module. The code raises an segmentation fault. After looking at the dmesg, I notice that it is because page table does not know how to translate the virtual address (i.e., 0xfec00000).
Then I use the ioremap() in the kernel module, it works.
#include <linux/module.h>
#include <linux/init.h>
#include <asm/io.h>
MODULE_LICENSE("Dual BSD/GPL");
static int hello_init(void)
{
// IO APIC base is 0xfec00000
// IO APIC index: 0xfec00000
// IO APIC data: 0xfec00010
// The redicection table of the keyboard is at index 0x12
// please see southbridge manual for redirection table
// the original value of the redirection table entry is 0x939
// We change it to 0xa39, which enables SMI triggering
//
// if you want to compile this kernel moudule,
// please also change the Makefile to hello6.o
//
// just run the script enable_kb_SMI.sh to enable the SMI
// triggering
//
unsigned int IRQ1_entry;
void * IOAPIC_BASE = ioremap(0xfec00000, 32);
iowrite8(0x12, IOAPIC_BASE);
IRQ1_entry = ioread32((unsigned char*)IOAPIC_BASE + 0x10);
printk("IRQ1 Entry Value is: %x\n", IRQ1_entry);
iowrite8(0x12, IOAPIC_BASE);
iowrite32(0xA39, (unsigned char*)IOAPIC_BASE + 0x10);
printk("Successfully enable keyboard SMI triggering\n");
return 0;
}
static void hello_exit(void)
{
printk("Goodbye, crule world\n");
}
module_init(hello_init);
module_exit(hello_exit);
Showing posts with label memory. Show all posts
Showing posts with label memory. Show all posts
Thursday, October 9, 2014
Saturday, November 3, 2012
Flush the Instruction Cache
// flush the cache, eip is the current eip address
__asm__ __volatile__("wbinvd"); // write back cache and invalidate cache
__asm__ __volatile__(
"CLFLUSH (%0)"
:"=r"(eip));
wbinvd:
Writes back all modified cache lines in the processor’s internal cache to main memory and invalidates (flushes) the internal caches. The instruction then issues a special- function bus cycle that directs external caches to also write back modified data and another bus cycle to indicate that the external caches should be invalidated.
clfush:
Invalidates the cache line that contains the linear address specified with the source operand from all levels of the processor cache hierarchy (data and instruction). The invalidation is broadcast throughout the cache coherence domain. If, at any level of the cache hierarchy, the line is inconsistent with memory (dirty) it is written to memory before invalidation
Please see intel manual instruction volume for more details
Monday, July 30, 2012
Friday, June 8, 2012
How to Limit the Amount of Memory Available to OS
Linux:
set the mem=2000m as the boot arguments, then the Linux only use first 2000MB memory. If the total RAM is 2G, it reserves 48MB.
http://fengweizhang.blogspot.com/2012/06/boot-arguments-on-linux.html
Windows:
Add line
MaxPhyPage=0x7D000
at [386enh] section of C:\WINDOWS\system.ini
0x7D000 * 4KB = 2000MB
http://support.microsoft.com/kb/181862
set the mem=2000m as the boot arguments, then the Linux only use first 2000MB memory. If the total RAM is 2G, it reserves 48MB.
http://fengweizhang.blogspot.com/2012/06/boot-arguments-on-linux.html
Windows:
Add line
MaxPhyPage=0x7D000
at [386enh] section of C:\WINDOWS\system.ini
0x7D000 * 4KB = 2000MB
http://support.microsoft.com/kb/181862
Saturday, April 21, 2012
Memory tool on Windows
vmmap
http://technet.microsoft.com/en-us/sysinternals/dd535533
cheatengine
http://www.cheatengine.org/
http://technet.microsoft.com/en-us/sysinternals/dd535533
cheatengine
http://www.cheatengine.org/
Thursday, April 19, 2012
VMware fusion snapshot
VMware Fusion snapshot saves the whole memory image file when you take a snapshot. You can find the memory image in the VM folder.
Here are some more detailed info about VMware snapshot
http://www.vmware.com/support/ws4/doc/preserve_snapshot_ws.html
Here are some more detailed info about VMware snapshot
http://www.vmware.com/support/ws4/doc/preserve_snapshot_ws.html
Saturday, April 14, 2012
Disable PAE on Windows XP SP3
Go to computer -> properties, it will show in the hardware specification if the PAE enabled.
Enabling PAE (by setting bit 5, PAE, of the system register
Enabling PAE (by setting bit 5, PAE, of the system register
CR4), which is the sixth bit from the left.
Disable method:
Normal boot.ini with PAE & DEP
multi(0)disk(0)rdisk(0)partition(1)\WINDOWS="Micro soft Windows XP Pro x86" /noexecute=optin /fastdetect
Disabled DEP & PAE
multi(0)disk(0)rdisk(0)partition(1)\WINDOWS="Micro soft Windows XP Pro x86" /execute /fastdetect
multi(0)disk(0)rdisk(0)partition(1)\WINDOWS="Micro soft Windows XP Pro x86" /noexecute=optin /fastdetect
Disabled DEP & PAE
multi(0)disk(0)rdisk(0)partition(1)\WINDOWS="Micro soft Windows XP Pro x86" /execute /fastdetect
__________________
Tuesday, November 1, 2011
Process Address Space
1. Each process has a process descriptor, and the location is in Kernel Space (3G-4G)
e.g. virtual address: 0xF44F7930, physical address: 0x344F7930
2. Each process has a memory descriptor, and the location is in Kernel Space (3G-4G)
e.g. virtual address: 0xF6CEA900, physical address: 0x36CEA900
3. Each process has a CR3 value and page directory and page table are in Kernel Space (3G-4G). And the value in CR3 register is a physical address. and value in pgd field of mm_struct is a virtual address. And pgd = CR3 + PAGE_OFFSET
e.g. CR3: 0x36D1C000, pgd:0xF6D1C000
4. Static code of process is in User Space (0G- 3G). The physical address of static is non-continuous, and it is allocated by page (4K).
e.g. virtual address: 0x8048000 - 0x8048DBC
5. Different process could have same linear address space.
e.g. static code of Firefox: 0x8048000 - 0x806D333; static code of Minicom: 0x8048000 - 0x805E333
e.g. virtual address: 0xF44F7930, physical address: 0x344F7930
2. Each process has a memory descriptor, and the location is in Kernel Space (3G-4G)
e.g. virtual address: 0xF6CEA900, physical address: 0x36CEA900
3. Each process has a CR3 value and page directory and page table are in Kernel Space (3G-4G). And the value in CR3 register is a physical address. and value in pgd field of mm_struct is a virtual address. And pgd = CR3 + PAGE_OFFSET
e.g. CR3: 0x36D1C000, pgd:0xF6D1C000
4. Static code of process is in User Space (0G- 3G). The physical address of static is non-continuous, and it is allocated by page (4K).
e.g. virtual address: 0x8048000 - 0x8048DBC
5. Different process could have same linear address space.
e.g. static code of Firefox: 0x8048000 - 0x806D333; static code of Minicom: 0x8048000 - 0x805E333
Friday, October 28, 2011
Thursday, October 27, 2011
Wednesday, September 21, 2011
Understanding the kernel code, and CR3 register
Recently, I was working on the kernel code and CR3 register. This article is going to record what I have learn.
First Question: How can we get the kernel code of Operating System?
Get Virtual Address of kernel code:
$ cat /boot/System.map-2.6.32-33-generic | grep text
c0100000 T_text
The first one is start virtual address of kernel code
Get Physical Address of kernel code:
$ cat /proc/iomem
00100000-00590de6 : Kernel Code
More info: please see
http://fengweizhang.blogspot.com/2010/12/boot-cat-system.html
http://jianggmulab.blogspot.com/2009/09/blog-post.html
Second Question: How to translate virtual address to physical address?
Control Register 3 (CR3) stores the base address of Page Directory Table. More info please see page 47 in ULK book.
Third Question: Which CR3 I should use to translate VA to PA of kernel code?
Any CR3. For each process, it has its own address spaces and CR3. No matter which processes the operating system is running, the virtual address and physical address of kernel code will never change. Although the CR3 is different depends on the running process, same VA will map to same PA by CR3.
Each process has its own address space. From the virtual address point of view, it has some address space at 0-3G region, and it also has some address space at 3-4G region (this is for kernel mode). All Processes get same mappings for the kernel address space (3-4G). Each process also has its own page directory table and page tables. CR3 is the base address of page directory table. The address space at 3-4G region must have its own translation entries in page directory table and page tables. These entries are always same in different page directory table and page tables.
Process 1 has virtual address space from 0xc0100000-0xc0590de6 (kernel code), translate to physical address is 0x00100000-0x00590de6
Process 2 has virtual address space from 0xc0100000-0xc0590de6 (kernel code), translate to physical address is 0x00100000-0x00590de6
Thus, process 1 and process 2 has same kernel memory mappings. (CR3 is different)
Monday, September 19, 2011
cat /proc/iomem
This is command shows the io memory map
This is the virtual address (linear address in Linux).
For example, it tells you the virtual address of kernel code.
If you want to get the kernel code, you could write a kenel module, and read the code out.
[root@localhost fengweiWorkSpace]# cat /proc/iomem
00010000-0009e3ff : System RAM
000a0000-000bffff : Video RAM area
000c0000-000cefff : Video ROM
000d3800-000d3fff : Adapter ROM
000f0000-000fffff : System ROM
00100000-7ddff7ff : System RAM
00400000-00620dc5 : Kernel code
00620dc6-007039fb : Kernel data
7ddff800-7de53bff : ACPI Non-volatile Storage
7de53c00-7de55bff : ACPI Tables
7de55c00-7dffffff : reserved
80000000-800fffff : PCI Bus #01
80000000-8001ffff : 0000:01:00.0
80020000-8002ffff : 0000:01:00.0
80100000-801fffff : PCI Bus #03
80100000-8010ffff : 0000:03:00.0
80110000-80110fff : 0000:03:02.0
80200000-8021ffff : 0000:00:19.0
80200000-8021ffff : e1000e
80220000-80223fff : 0000:00:1b.0
80220000-80223fff : ICH HD audio
80224000-80224fff : 0000:00:03.3
80225000-80225fff : 0000:00:19.0
80225000-80225fff : e1000e
80226000-802263ff : 0000:00:1a.7
80226000-802263ff : ehci_hcd
80226400-802264ff : 0000:00:1f.3
d0000000-dfffffff : PCI Bus #01
d0000000-dfffffff : 0000:01:00.0
e0000000-fed003ff : reserved
fed20000-fed9ffff : reserved
fedad000-fedad00f : 0000:00:03.0
fee00000-feefffff : reserved
ff970000-ff9707ff : 0000:00:1f.2
ff970000-ff9707ff : ahci
ff980800-ff980bff : 0000:00:1d.7
ff980800-ff980bff : ehci_hcd
ffb00000-ffffffff : reserved
This is the virtual address (linear address in Linux).
For example, it tells you the virtual address of kernel code.
If you want to get the kernel code, you could write a kenel module, and read the code out.
[root@localhost fengweiWorkSpace]# cat /proc/iomem
00010000-0009e3ff : System RAM
000a0000-000bffff : Video RAM area
000c0000-000cefff : Video ROM
000d3800-000d3fff : Adapter ROM
000f0000-000fffff : System ROM
00100000-7ddff7ff : System RAM
00400000-00620dc5 : Kernel code
00620dc6-007039fb : Kernel data
7ddff800-7de53bff : ACPI Non-volatile Storage
7de53c00-7de55bff : ACPI Tables
7de55c00-7dffffff : reserved
80000000-800fffff : PCI Bus #01
80000000-8001ffff : 0000:01:00.0
80020000-8002ffff : 0000:01:00.0
80100000-801fffff : PCI Bus #03
80100000-8010ffff : 0000:03:00.0
80110000-80110fff : 0000:03:02.0
80200000-8021ffff : 0000:00:19.0
80200000-8021ffff : e1000e
80220000-80223fff : 0000:00:1b.0
80220000-80223fff : ICH HD audio
80224000-80224fff : 0000:00:03.3
80225000-80225fff : 0000:00:19.0
80225000-80225fff : e1000e
80226000-802263ff : 0000:00:1a.7
80226000-802263ff : ehci_hcd
80226400-802264ff : 0000:00:1f.3
d0000000-dfffffff : PCI Bus #01
d0000000-dfffffff : 0000:01:00.0
e0000000-fed003ff : reserved
fed20000-fed9ffff : reserved
fedad000-fedad00f : 0000:00:03.0
fee00000-feefffff : reserved
ff970000-ff9707ff : 0000:00:1f.2
ff970000-ff9707ff : ahci
ff980800-ff980bff : 0000:00:1d.7
ff980800-ff980bff : ehci_hcd
ffb00000-ffffffff : reserved
Wednesday, August 3, 2011
NAND and NOR Flash
NOR flash used as main memory
NAND flash used as secondary memroy.
In embeded device:
used as main memory: ROM, EPROM, NOR flash, SRAM, DRAM
used as secondary memory: NAND flash, SD, DOC(disk on chip).
NOR and NAND flash differ in two important ways:
NAND flash used as secondary memroy.
In embeded device:
used as main memory: ROM, EPROM, NOR flash, SRAM, DRAM
used as secondary memory: NAND flash, SD, DOC(disk on chip).
NOR and NAND flash differ in two important ways:
- the connections of the individual memory cells are different
- the interface provided for reading and writing the memory is different (NOR allows random-access for reading, NAND allows only page access)
Saturday, February 5, 2011
NVRAM, DRAM, SRAM
Non-Volatile random access memory.
E.g. flash disk
it will not loose data after power off
Dynamic random access memory (DRAM) and Static random access memory (SRAM) will need power to keep data.
DRAM: volatile, need periodically refreshed (home PCs are DRAM)
SRAM: volatile
NVRAM fast than disk, but it more expensive
E.g. flash disk
it will not loose data after power off
Dynamic random access memory (DRAM) and Static random access memory (SRAM) will need power to keep data.
DRAM: volatile, need periodically refreshed (home PCs are DRAM)
SRAM: volatile
NVRAM fast than disk, but it more expensive
Tuesday, January 25, 2011
Access any memory by using kernel module
If you write a user program, it cannot read all the memory.
userprogram:
This program will give your segmentation fault when you run it.
Remember, CPU only understand virtual address.
Solution, write a kernel module to access any memory
MODULE_LICENSE("Dual BSD/GPL");
static int hello_init(void)
{
char mem[SIZE];
int i;
void *virtualAddr ;
// virtualAddr = ioremap(PHYSTARTADDR, SIZE);
virtualAddr = VIRSTARTADDR;
for(i = 0; i< SIZE; i++)
printk("%x", *(char*)(virtualAddr+i));
printk("\nhello, world\n");
return 0;
}
static void hello_exit(void)
{
printk("Goodbye, crule world\n");
}
module_init(hello_init);
module_exit(hello_exit);
userprogram:
virtualAddr = 0xc0010203 // randomly define virtual address
for(i = 0; i< SIZE; i++)
printf("%x", *(char*)(virtualAddr+i));
printf("%x", *(char*)(virtualAddr+i));
This program will give your segmentation fault when you run it.
Remember, CPU only understand virtual address.
Solution, write a kernel module to access any memory
#include <linux/module.h>
#include <linux/init.h>
#include <asm/io.h>
// 1G = 0x40000000
// trusted OS kernel code physical address is (0x400000, 0x620de5)
// add 1G, then test if it could access from this untrusted OS
#define PHYSTARTADDR 0x40400000
#define PHYENDADDR 0x40620de5
// this is the virtual address of kernel code
#define VIRSTARTADDR 0xc0400000
#define VIRENDADDR 0xc0620de5
#define SIZE 100
#include <linux/init.h>
#include <asm/io.h>
// 1G = 0x40000000
// trusted OS kernel code physical address is (0x400000, 0x620de5)
// add 1G, then test if it could access from this untrusted OS
#define PHYSTARTADDR 0x40400000
#define PHYENDADDR 0x40620de5
// this is the virtual address of kernel code
#define VIRSTARTADDR 0xc0400000
#define VIRENDADDR 0xc0620de5
#define SIZE 100
MODULE_LICENSE("Dual BSD/GPL");
static int hello_init(void)
{
char mem[SIZE];
int i;
void *virtualAddr ;
// if we want to access the memory range beyond current DIMM
// we could use ioremap to create the pagetables, so cpu will understand
// this virtual address. // we could use ioremap to create the pagetables, so cpu will understand
// virtualAddr = ioremap(PHYSTARTADDR, SIZE);
// this case, we just want to read all the current memory range,
// which is DIMM has been initialized. virtualAddr = VIRSTARTADDR;
for(i = 0; i< SIZE; i++)
printk("%x", *(char*)(virtualAddr+i));
printk("\nhello, world\n");
return 0;
}
static void hello_exit(void)
{
printk("Goodbye, crule world\n");
}
module_init(hello_init);
module_exit(hello_exit);
Sunday, January 16, 2011
Memory System Configuration
OS: Cent OS 5.5
Chipset: AMDK8
you could get memory system configuration from following file:
/sys/bus/pci/devices/0000\:00\:18.0/ /* this is bus 0, device 18, function 0 registers */
E.g.
/* This is use hexdump to see the memory configuration */
hexdump /sys/bus/pci/devices/0000\:00\:18.0/config -v > ~/f0_conf
hexdump /sys/bus/pci/devices/0000\:00\:18.1/config -v > ~/f1_conf
hexdump /sys/bus/pci/devices/0000\:00\:18.2/config -v > ~/f2_conf
hexdump /sys/bus/pci/devices/0000\:00\:18.3/config -v > ~/f3_conf
For the meaning of these 256 bytes, please read the BIOS Kernel Development Guide(BKDG). There is another article about this
Chipset: AMDK8
you could get memory system configuration from following file:
/sys/bus/pci/devices/0000\:00\:18.0/ /* this is bus 0, device 18, function 0 registers */
E.g.
/* This is use hexdump to see the memory configuration */
hexdump /sys/bus/pci/devices/0000\:00\:18.0/config -v > ~/f0_conf
hexdump /sys/bus/pci/devices/0000\:00\:18.1/config -v > ~/f1_conf
hexdump /sys/bus/pci/devices/0000\:00\:18.2/config -v > ~/f2_conf
hexdump /sys/bus/pci/devices/0000\:00\:18.3/config -v > ~/f3_conf
For the meaning of these 256 bytes, please read the BIOS Kernel Development Guide(BKDG). There is another article about this
Wednesday, December 29, 2010
/dev/mem Read Physical Memory
This is the physical memory address, if you want to read/write physical memory, you can open this file using fopen() for open(), and read/write it. For example, you can read/write SMRAM at 0xa0000
However, it cannot read /dev/mem mmap after 0x101000, but you could use mmap to solve this problem. please see article.
http://my.opera.com/yangguangxiang/blog/2008/02/17/dev-mem
在2.4,可以直接打开/dev/mem,然后读取。
在2.6,直接打开/dev/mem后,只可以读取前0x101000部分的内容(ubuntu)。大约是1MB加4KB。读取后面的内容将出现"open not permitted"错误。
解决的方法是使用mmap()。routine如下:
f = open("/dev/mem", O_RDONLY);
my_mem = mmap (0, 0x1000, PROT_READ, MAP_SHARED, f, 0x34f000);
if (my_mem == MAP_FAILED)
printf("map failed %s\n",strerror(errno));
通过my_mem就可以得到0x101000之后的内存内容了。
However, it cannot read /dev/mem mmap after 0x101000, but you could use mmap to solve this problem. please see article.
http://my.opera.com/yangguangxiang/blog/2008/02/17/dev-mem
在2.4,可以直接打开/dev/mem,然后读取。
在2.6,直接打开/dev/mem后,只可以读取前0x101000部分的内容(ubuntu)。大约是1MB加4KB。读取后面的内容将出现"open not permitted"错误。
解决的方法是使用mmap()。routine如下:
f = open("/dev/mem", O_RDONLY);
my_mem = mmap (0, 0x1000, PROT_READ, MAP_SHARED, f, 0x34f000);
if (my_mem == MAP_FAILED)
printf("map failed %s\n",strerror(errno));
通过my_mem就可以得到0x101000之后的内存内容了。
understanding mmap()
#include <sys/mman.h>
void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);
The basic idea is to map the content of a file to memory.
size_t length: the number of bytes you want to map
off_t offset: the start address of file you want to map. or you could say the offset of the current file you are going to map it to memory.
int fd: the file descriptor you the file.
int prot: memory protection of the memory just mapped.
The prot argument describes the desired memory protection of the map‐
ping (and must not conflict with the open mode of the file). It is
either PROT_NONE or the bitwise OR of one or more of the following
flags:
PROT_EXEC Pages may be executed.
PROT_READ Pages may be read.
PROT_WRITE Pages may be written.
PROT_NONE Pages may not be accessed.
int flags: mapped memory is shared with other process or private.
here is the example of mmap usage, but this is not working:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/mman.h>
#define STARTADDR 0x400000
#define ENDADDR 0x620de6
#define SIZE ENDADDR - STARTADDR
int main(int argc, char *argv[])
{
int fd1 = open("/dev/mem", O_RDONLY);
if(fd1 == -1)
{
fprintf(stderr, "open error\n");
exit(1);
}
int fd2 = open("staticMem", O_CREAT | O_RDWR);
if(fd1 == -1)
{
fprintf(stderr, "open error\n");
exit(1);
}
void* my_mem = mmap(0, SIZE, PROT_READ, MAP_SHARED, fd1, STARTADDR);
if(my_mem == MAP_FAILED)
{
fprintf(stderr, "map failed\n");
exit(1);
}
if(write(fd2, my_mem, SIZE)!= SIZE)
{
fprintf(stderr, "write error\n");
exit(1);
}
return 1;
}
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/mman.h>
#define STARTADDR 0x400000
#define ENDADDR 0x620de6
#define SIZE ENDADDR - STARTADDR
int main(int argc, char *argv[])
{
int fd1 = open("/dev/mem", O_RDONLY);
if(fd1 == -1)
{
fprintf(stderr, "open error\n");
exit(1);
}
int fd2 = open("staticMem", O_CREAT | O_RDWR);
if(fd1 == -1)
{
fprintf(stderr, "open error\n");
exit(1);
}
void* my_mem = mmap(0, SIZE, PROT_READ, MAP_SHARED, fd1, STARTADDR);
if(my_mem == MAP_FAILED)
{
fprintf(stderr, "map failed\n");
exit(1);
}
if(write(fd2, my_mem, SIZE)!= SIZE)
{
fprintf(stderr, "write error\n");
exit(1);
}
return 1;
}
logical address, linear address(virtual address), physical address
logical address: before segementation unit translate, in projected mode, it is same value as linear or virtual address. because linux does not use segmentation.
linear address or virtual address: Before paging unit
physical address: not necessary map to RAM, to could be mapped to other device(ROM, PCI device)
linear address or virtual address: Before paging unit
physical address: not necessary map to RAM, to could be mapped to other device(ROM, PCI device)
Friday, December 24, 2010
how to get the physicall address of kernel code
$ cat /boot/System.map-2.6.32-27-generic | grep text
This command will give you virtual address. The first one is the start of kernel code, For example, on my Ubuntu:$ cat /boot/System.map-2.6.32-27-generic | grep text
c0100000 T _text
If you change the c to 0, you changed the virtual address to physical address on Linux.
Why? please see: http://jianggmulab.blogspot.com/2009/09/blog-post.html$ cat /boot/System.map-2.6.32-27-generic | grep etext
This one will give you the end virtual address of kernel code. $ cat /proc/iomem
This command will give your general picture of current memory, and all the address are physical address. For example, on my Ubuntu:00100000-00592a36 : Kernel code
Subscribe to:
Posts (Atom)