Dave Anderson wrote:
Rachita Kothiyal wrote:
> Hi Dave
>
> Running 'dev -p' command on PowerPC systems with virtual devices (ie
> no real PCI devices) fails with the following message:
>
> dev: invalid kernel virtual address: 98 type: "pci bus number"
>
> It should instead report that there are no _real_ PCI devices to list.
> The following patch addresses this issue. Currently it just prints a
> message letting the user know of the absence of pci devices, but it
> might be a good idea to list down the virtual devices present in the
> system in such cases. I am working on a patch for that too, probably
> will discuss that on another thread.
>
> Please provide your comments/suggestions.
>
> Thanks
> Rachita
Hi Rachita,
Yep -- in fact I see that the same thing happens on xen kernels
as well. I'll test your patch out on a few other architectures, and
if all goes well, I'll queue it for the next release.
Thanks again,
Dave
>
>
> On PowerPC machines configured with virtual devices(VIO) it is possible
> that there are no _real_ PCI devices. Hence it is reasonable that 'dev -p'
> would not list anything. This patch identifies such cases and displays a
> message appropriately.
>
> Signed-off-by: Rachita Kothiyal <rachita(a)in.ibm.com>
> ---
>
> dev.c | 30 +++++++++++++++++++++++++++---
> 1 files changed, 27 insertions(+), 3 deletions(-)
>
> diff -puN dev.c~fix-vio-pci-device dev.c
> --- crash-4.0-3.9/dev.c~fix-vio-pci-device 2006-12-22 13:32:02.737262096 +0530
> +++ crash-4.0-3.9-rachita/dev.c 2006-12-22 13:48:44.984897296 +0530
> @@ -1955,13 +1955,11 @@ do_pci(void)
> unsigned int class;
> unsigned short device, vendor;
> unsigned char busno;
> - ulong *devlist, bus, devfn, tmp;
> + ulong *devlist, bus, devfn, tmp, prev, next;
> char buf1[BUFSIZE];
> char buf2[BUFSIZE];
> char buf3[BUFSIZE];
>
> - fprintf(fp, "%s BU:SL.FN CLASS: VENDOR-DEVICE\n",
> - mkstring(buf1, VADDR_PRLEN, CENTER|LJUST, "PCI_DEV"));
>
> BZERO(&pcilist_data, sizeof(struct list_data));
>
> @@ -1972,11 +1970,34 @@ do_pci(void)
> FAULT_ON_ERROR);
> pcilist_data.end = symbol_value("pci_devices");
> pcilist_data.list_head_offset = OFFSET(pci_dev_global_list);
> + readmem(symbol_value("pci_devices") +
OFFSET(list_head_prev),
> + KVADDR, &prev, sizeof(void *), "list head
prev",
> + FAULT_ON_ERROR);
> + /*
> + * Check if this system does not have any PCI devices.
> + * Possible on PowerPC machines with VIO configured.
> + */
> + if ((pcilist_data.start == pcilist_data.end) &&
> + (prev == pcilist_data.end)) {
> + fprintf(fp, "No PCI devices found on this
system.\n");
> + return;
> + }
>
> } else {
> get_symbol_data("pci_devices", sizeof(void *),
> &pcilist_data.start);
> pcilist_data.member_offset = OFFSET(pci_dev_next);
> + /*
> + * Check if this system does not have any PCI devices.
> + * Possible on PowerPC machines with VIO configured.
> + */
> + readmem(pcilist_data.start + pcilist_data.member_offset,
> + KVADDR, &next, sizeof(void *), "pci dev
next",
> + FAULT_ON_ERROR);
> + if (!next) {
> + fprintf(fp, "No PCI devices found on this
system.\n");
> + return;
> + }
> }
>
> hq_open();
> @@ -1985,6 +2006,9 @@ do_pci(void)
> devcnt = retrieve_list(devlist, devcnt);
> hq_close();
>
> + fprintf(fp, "%s BU:SL.FN CLASS: VENDOR-DEVICE\n",
> + mkstring(buf1, VADDR_PRLEN, CENTER|LJUST, "PCI_DEV"));
> +
> for (i = 0; i < devcnt; i++) {
>
> /*
> _
Hi Rachita,
Found a few other quirks -- kernels that don't have the "pci_device"
symbol at all, and another 2.6.7-era kernel compiled with gcc 3.4.1
that didn't have debuginfo data for the pci_dev structure.
Here's what I'm going with to cover all bases.
Thanks,
Dave
Index: dev.c
===================================================================
RCS file: /nfs/projects/cvs/crash/dev.c,v
retrieving revision 1.13
diff -u -r1.13 dev.c
--- dev.c 23 Nov 2005 16:09:44 -0000 1.13
+++ dev.c 22 Dec 2006 18:48:25 -0000
@@ -1955,35 +1955,53 @@
unsigned int class;
unsigned short device, vendor;
unsigned char busno;
- ulong *devlist, bus, devfn, tmp;
+ ulong *devlist, bus, devfn, prev, next;
char buf1[BUFSIZE];
char buf2[BUFSIZE];
char buf3[BUFSIZE];
- fprintf(fp, "%s BU:SL.FN CLASS: VENDOR-DEVICE\n",
- mkstring(buf1, VADDR_PRLEN, CENTER|LJUST, "PCI_DEV"));
+ if (!symbol_exists("pci_devices"))
+ error(FATAL, "no PCI devices found on this system.\n");
BZERO(&pcilist_data, sizeof(struct list_data));
if (VALID_MEMBER(pci_dev_global_list)) {
- get_symbol_data("pci_devices", sizeof(void *), &tmp);
- readmem(tmp + OFFSET(list_head_next), KVADDR,
- &pcilist_data.start, sizeof(void *), "pci
devices",
- FAULT_ON_ERROR);
+ get_symbol_data("pci_devices", sizeof(void *),
&pcilist_data.start);
pcilist_data.end = symbol_value("pci_devices");
pcilist_data.list_head_offset = OFFSET(pci_dev_global_list);
+ readmem(symbol_value("pci_devices") + OFFSET(list_head_prev),
+ KVADDR, &prev, sizeof(void *), "list head prev",
+ FAULT_ON_ERROR);
+ /*
+ * Check if this system does not have any PCI devices.
+ */
+ if ((pcilist_data.start == pcilist_data.end) &&
+ (prev == pcilist_data.end))
+ error(FATAL, "no PCI devices found on this system.\n");
- } else {
+ } else if (VALID_MEMBER(pci_dev_next)) {
get_symbol_data("pci_devices", sizeof(void *),
&pcilist_data.start);
pcilist_data.member_offset = OFFSET(pci_dev_next);
- }
+ /*
+ * Check if this system does not have any PCI devices.
+ */
+ readmem(pcilist_data.start + pcilist_data.member_offset,
+ KVADDR, &next, sizeof(void *), "pci dev next",
+ FAULT_ON_ERROR);
+ if (!next)
+ error(FATAL, "no PCI devices found on this system.\n");
+ } else
+ option_not_supported('p');
hq_open();
devcnt = do_list(&pcilist_data);
devlist = (ulong *)GETBUF(devcnt * sizeof(ulong));
devcnt = retrieve_list(devlist, devcnt);
hq_close();
+
+ fprintf(fp, "%s BU:SL.FN CLASS: VENDOR-DEVICE\n",
+ mkstring(buf1, VADDR_PRLEN, CENTER|LJUST, "PCI_DEV"));
for (i = 0; i < devcnt; i++) {