1 (* Memory info command for virtual domains.
2 (C) Copyright 2008 Richard W.M. Jones, Red Hat Inc.
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 open Virt_mem_gettext.Gettext
26 open Kernel_net_device
28 type linkage = Next | DevList of int
30 let rec find_net_devices debug image ksymmap kernel_version =
31 if not (net_device_known kernel_version) then (
32 eprintf (f_"%s: %s: unknown kernel version
33 Try a newer version of virt-mem, or if the guest is not from a
34 supported Linux distribution, see this page about adding support:
35 http://et.redhat.com/~rjones/virt-mem/faq.html\n")
36 image.domname kernel_version;
39 let size = net_device_size kernel_version in
41 (* In kernels < around 2.6.22, this is a simple linked list:
42 * dev_base -> next -> next
43 * In kernels >= 2.6.23, this is a list_head:
44 * dev_base_head -> list_head dev_list -> ...
47 let { field_available = available } =
48 field_signature_of_net_device_next kernel_version in
52 let { field_available = available; field_offset = offset } =
53 field_signature_of_net_device_dev_list'next kernel_version in
57 eprintf (f_"%s: kernel net_device table is not linked through either next pointer or dev_list list_head. Cannot read net devices.\n") image.domname;
65 printf "linkage = Next\n%!";
67 (* Linkage through old-style chain of next pointers. *)
69 try Some (Ksymmap.find "dev_base" ksymmap)
71 eprintf (f_"%s: could not find dev_base symbol in kernel image\n") image.domname;
76 do_next image kernel_version dev_base size
79 | Some (DevList offset) ->
80 printf "linkage = DevList %d\n%!" offset;
82 (* Linkage through new-style list_head dev_list. *)
84 try Some (Ksymmap.find "dev_base_head" ksymmap)
86 eprintf (f_"%s: could not find dev_base_head symbol in kernel image\n") image.domname;
88 (match dev_base_head with
90 | Some dev_base_head ->
92 Virt_mem_mmap.follow_pointer image.mem dev_base_head in
94 do_dev_list image kernel_version dev_base_head offset size
98 (* Iterate dev_base_head -> list_head dev_list -> ... *)
99 and do_dev_list image kernel_version dev_base_head offset size =
100 (* The list_head points into the middle of the structure.
101 * Adjust this address to point to the start of the
104 let addr = Int64.sub dev_base_head (Int64.of_int offset) in
106 printf "do_dev_list, size = %d\n" size;
109 let rec loop image addr =
110 let mapped = Virt_mem_mmap.is_mapped_range image.mem addr size in
113 Virt_mem_types.load_memory image addr size
116 let dev = get_net_device kernel_version image.mem addr in
117 printf "net_device_name = %S\n" dev.net_device_name;
118 let addr = Option.get dev.net_device_dev_list'next in
119 if addr <> dev_base_head then
125 image, Some dev_base_head
127 (* Iterate dev_base -> next -> next ... *)
128 and do_next image kernel_version addr size =
129 printf "do_next, size = %d\n" size;
132 let rec loop image addr =
134 let mapped = Virt_mem_mmap.is_mapped_range image.mem addr size in
137 Virt_mem_types.load_memory image addr size
140 let dev = get_net_device kernel_version image.mem addr in
141 printf "net_device_name = %S\n" dev.net_device_name;
143 match dev.net_device_next with
144 | None -> assert false | Some addr -> addr in