Difference between virtual address and physical address? - memory-address

Kindly explain the difference between the virtual and physical addresses based on the following example. Please explain which address is specifically used here and how to use the other address in the same place.
Also, how can the two always be distinguished.
code:
if(fork()==0)
{
a=a+5;
printf("%d%d", a, &a);
}
else
{
a=a-5;
printf("%d%d", a, &a);
}
What address does &a refer to in both the statements?

&a may refer two different addresses if you declare variable a independently in if & else blocks.
But if variable a is declared above "if",then in either of the case, variable "a" will be having the same physical address which can be accessed by &a.
When you add or subtract values from "a", you are altering the content stored in the memory where "a" is stored, means the value of a, not the address.
In you case, you are not altering the address of a, as it is the physical address.
If you really want to play with the address then have a pointer pointing to a like
*p = &a;
p+=5;
p-=5;
This way you can go five memory blocks forward & backward (one block size depends on type of variable "a") in memory.
For more on virtual address: refer here
Hope that helps.

Related

Will data be copied byte by byte when moving a variable?

I'm new to rust, and I am wondering what exactly happens when moving a variable.
struct Point {
x: i32,
y: i32,
}
fn main() {
let p = Point { x: 1, y: 1 };
let q = p;
}
When let q = p;, will the data (size of which is 8 bytes) be copied from a memory address to another? Since p is moved here thus it cannot be used anymore, I think it is good to make q's underlying memory address equal to p's. In another word, I think it is OK that nothing is copied in the machine code.
So my question is: will data be copied byte by byte when moving a variable? If it will, why?
[W]ill data be copied byte by byte when moving a variable?
In general, yes. To move a value, Rust simply performs a bitwise copy. If the value is not Copy, the source won't be used anymore after the move. If the value is Copy, both the source and the destination can be used.
However, there are many cases when the compiler backend can eliminate the copy by proving that the code beahves identical without the copy. This optimization happens completely in LLVM. In your example, the LLVM IR still contains the instructions to move the data, but the generated code does not contain the move even in debug mode.
If it will, why?
There are many reasons why the compiler can be unable to use the same memory for source and destination. In your example, with two variables in the same stack frame, it's easy to see that the move is not needed, but the code is a bit pointless anyway (though sometimes people do move values inside a function to make a variable immutable).
Here are just a few illustrations why the compiler may be unable to reuse the source memory for the destination:
The source value may be on the stack, while the destination is on the heap or vice versa. The statement let b = Box::new(3); will move the value 3 from the stack to the heap'; let i = *b; will move it from the heap back to the stack. It's still possible that the compiler can eliminate these moves, e.g. by writing the constant 3 to the heap immediately, without writing it to the stack first.
Source and destination may be on different stack frames, when moving values across functions – e.g. when passing a value into a function, or when returning a value from a function.
Source an destination values may be stored in struct fields, so they need to have the right offset inside the struct.
These are just a few examples. The takeaway is that in general, a move may result in a bitwise copy. Keep in mind that a bitwise copy is very cheap, though, and that the optimizer usually does a good job, so you should only worry about this if you actually have a proven performance bottleneck.

How Control Registers are accessed in Linux

i have been reading Linux source code ported on to a propriety platform based on ARM Cortex -A7 MPCore - NEON Architecture
The code below shows how a control register of a module is modified up on calling an API
drivers\module\module-specific_file.c
static inline void API(....)
{
if (set)
__raw_writel(msk, (void *)((u32) (reg) + 0x1000));
else
{
__raw_writel(msk, (void *)((u32) (reg) + 0x2000));
}
}
in the above code reg is actually a virtual address and msk is a mask lets say x7FF and set is a parameter passed which conveys request of set/clear
but actually my doubt is how does modifying the control register address is modifying the value to be written to register ... ?? further if i look at the api which is been called it looks like below
arch\arm\include\asm\Io.h
static inline void __raw_writel(u32 val, volatile void __iomem *addr)
{
asm volatile("str %1, %0"
: "+Qo" (*(volatile u32 __force *)addr)
: "r" (val));
}
if any one have come across this kind of accessing control registers please let me know how actually content of registers are modified by modifying the virtual address.
As I know, registers are mapped in virtual address space. Have a look at /proc/iomem for example, you'll see mapped registers addresses and what hardware they are belong. The addresses of registers are strictly determined by hardware developers.
Typically, to map register address one should call ioremap function. It returns the address. Often this address is the base address, where the register addresses begin. To write something in register you just need to write the data in this address plus the resister offset.
E.g.: On ARM PXA320, there is a set of LCD registers. Somewhere ion driver code one may see - ioremap(BASE_ADDR, SIZE_OF_ADDR_SET);
In order to write __raw_write(value, base_addr + offset) function is used.

How does this way of writing data to a specific physical memory address work?

I want to write data to an arbitrary physical memory address to test the error detection and correction feature of my system. One code segment in an existing kernel module is written like this:
u32 addr;
struct page *page;
void *mem;
pci_read_config_dword(priv->mc, I5100_MEMEINJADDRMAT, &addr);
/* Inject error by writing to address */
page = pfn_to_page(addr >> PAGE_SHIFT);
mem = kmap(page) + (addr & (~PAGE_MASK));
*((volatile u32*) (mem)) = 0x01010101;
kunmap(page);
I5100_MEMEINJADDRMAT is the register address of a register in i5100 memory controller. Basically, the memory address is retrieved in that register. I don't understand the remaining code, starting from retrieving a page then perform bitwise operations.
As far as I understand, pfn_to_page is used to get a page that includes a particular physical address by passing in a page frame number as argument. The addr >> PAGE_SHIFT part is to translate from a given address to its corresponding page frame number. But, I don't understand how to use PAGE_SHIFT correctly? What should be the correct data type to use with PAGE_SHIFT?
kmap() returns the appropriate virtual page address then add the offset to get the correct pointer to a virtual memory address. What does (addr & (~PAGE_MASK)) actually do?
My task is to write error injection to a physical address? But the above code seems to write to a virtual address. Is there any other way?
This:
(addr & (~PAGE_MASK))
will clear the bits in addr that are set in PAGE_MASK. Assuming a page size of 4 KB, the PAGE_MASK will likely have its 12 least significant bits set, since 212 = 4096.
So, PAGE_MASK is 0x00000fff. Then, the bit-wise inverse ~PAGE_MASK is simply 0xfffff000, so when addr is bitwise-and:ed with this, the lowest 12 bits of addr are cleared.
/* PAGE_SHIFT determines the page size */
#define PAGE_SHIFT 12
#define PAGE_SIZE (_AC(1,UL) << PAGE_SHIFT)
#define PAGE_MASK (~(PAGE_SIZE-1))
I found these definition in linux-source-3.2.0.
but I get PAGE_MASK is 0xfffff000
so I think this operator is clearing the highest 20bit, or try to get the value of lower 12 bit.
page = pfn_to_page(addr >> PAGE_SHIFT);
It gets the page address using page frame number (page frame number (pfn) is obtained shifting to right the address). Because least significant bits represent offset in the page (12 bits for x86). Page frame number is equal to 20 most significant bits of the physical address for x86.
You can apply shifting on pointer or integer data types. It depends on the situation.
(addr & (~PAGE_MASK)) gets inner offset of the frame. To access correct byte you should add offset to related page.
Virtual address represents physical address. As far as I know, there is no way other than using virtual address. Also, I should say this is kernel virtual space, it is different from userspace virtual addresses.Do not mix userspace with kernel space.

Is there a kernel module that returns exactly what a simple 'ifconfig' does?

I'm writing a kernel module that needs information about the local machine's interfaces just like the ones retuned by a simple 'ifconfig' command, I've searched a lot for it, but couldn't find anything
You can get all of that information through the struct net_device one way or another.
As Albert Veli said, you can get this struct net_device pointer using __dev_get_by_name().
If you tell us what information you need specifically we might even be able to point you to the correct fields.
Finding the MAC address is fairly simple:
struct net_device *dev = __dev_get_by_name("eth0");
dev->dev_addr; // is the MAC address
dev->stats.rx_dropped; // RX dropped packets. (stats has more statistics)
Finding the IP address is rather harder, but not impossible:
struct in_device *in_dev = rcu_dereference(dev->ip_ptr);
// in_dev has a list of IP addresses (because an interface can have multiple)
struct in_ifaddr *ifap;
for (ifap = in_dev->ifa_list; ifap != NULL;
ifap = ifap->ifa_next) {
ifap->ifa_address; // is the IPv4 address
}
(None of this was compile tested, so typos are possible.)
See for example the in6_dump_addrs function in net/ipv6/addrconf.c for how to get at addresses. For link properties like link layer address, see core/rtnetlink.c instead. ifconfig and its ioctls are obsolete (on Linux), so better don't think in terms of that now-bug-ridden program.

Difference between skbuff frags and frag_list

The sk_buff has two places where it can store the next fragmentation data:
skb_shinfo(head)->frag_list
skb_shinfo(head)->frags[]
What are the differences between these two ways to handle fragmentation?
Both are used for different cases.
frags[]
When your device supports scatter-gather I/O, and you want it to do the combining of data, etc., you can populate the frags[] structure starting with the second fragment till the nth fragment. The first fragment is always specified by the data and tail pointers. The rest of the fragments are filled in the frags[] structure. If you don't use scatter gather, this variable is empty.
frag_list
This is the list of IP fragments. This will be filled during ip_push_pending_frames.
Say your sk_buffs are in this arrangement,
sk_buff0->next = sk_buff1
sk_buff1->next = sk_buff2
...
sk_buffn-1->next = sk_buffn
After ip_push_pending_frames is called
sk_buff0->frag_list = sk_buff1
sk_buff1->next = sk_buff2
...
sk_buffn-1->next = sk_buffn
Simply put
frags[] are for scatter-gather I/O buffers
frag_list is for IP fragments
skb_shinfo(head)->frags[]
If the NIC supports SG I/O, __ip_append_data will copy user space data to skb_shinfo(head)->frags. The NIC driver (e.g., ixgbe_add_rx_frag) can also use these frags[] to carry the received network traffic; please note that every content in frags[] is a part of a complete packet. A complete packet consists of all frags[] + (skb->data ~ skb->tail).
skb_shinfo(head)->frag_list
This member is not used by IP fragmentation directly.
In __ip_make_skb(), the frag_list is used to collect all skbs from sk->sk_write_queue; some NIC drivers also use this frag_list for carrying a packet to the upper network stack. Every content/skb in frag_list is also not a complete packet; tcp_v4_send_ack -> ip_send_unicast_reply -> ip_push_pending_frames -> ip_finish_skb -> __ip_make_skb;

Resources