svn commit: r310630 - in head: include lib/libkvm
Andriy Gapon
avg at FreeBSD.org
Tue Dec 27 10:17:58 UTC 2016
Author: avg
Date: Tue Dec 27 10:17:56 2016
New Revision: 310630
URL: https://svnweb.freebsd.org/changeset/base/310630
Log:
libkvm: support access to vmm guest memory, allow writes to fwmem and vmm
This change consists of two parts:
- allow libkvm to recognize /dev/vmm/* character devices as devices that
provide access to the physical memory of a system (similarly to /dev/fwmem*)
- allow libkvm to recognize that /dev/vmm/* and /dev/fwmem* devices provide
access to the physical memory of live remote systems and, thus, the memory
is writable
As a result, it should be possible to run commands like
$ kgdb -w /path/to/kernel /dev/fwmem0.0
$ kgdb /path/to/kernel /dev/vmm/guest
Reviewed by: kib, jhb
MFC after: 2 weeks
Relnotes: yes
Sponsored by: Panzura
Differential Revision: https://reviews.freebsd.org/D8679
Modified:
head/include/paths.h
head/lib/libkvm/kvm.c
head/lib/libkvm/kvm_private.h
Modified: head/include/paths.h
==============================================================================
--- head/include/paths.h Tue Dec 27 09:40:07 2016 (r310629)
+++ head/include/paths.h Tue Dec 27 10:17:56 2016 (r310630)
@@ -99,6 +99,7 @@
#define _PATH_VARDB "/var/db/"
#define _PATH_VARRUN "/var/run/"
#define _PATH_VARTMP "/var/tmp/"
+#define _PATH_DEVVMM "/dev/vmm/"
#define _PATH_YP "/var/yp/"
#define _PATH_UUCPLOCK "/var/spool/lock/"
Modified: head/lib/libkvm/kvm.c
==============================================================================
--- head/lib/libkvm/kvm.c Tue Dec 27 09:40:07 2016 (r310629)
+++ head/lib/libkvm/kvm.c Tue Dec 27 10:17:56 2016 (r310630)
@@ -167,8 +167,10 @@ _kvm_open(kvm_t *kd, const char *uf, con
return (kd);
}
}
+
/*
- * This is a crash dump.
+ * This is either a crash dump or a remote live system with its physical
+ * memory fully accessible via a special device.
* Open the namelist fd and determine the architecture.
*/
if ((kd->nlfd = open(uf, O_RDONLY | O_CLOEXEC, 0)) < 0) {
@@ -177,8 +179,11 @@ _kvm_open(kvm_t *kd, const char *uf, con
}
if (_kvm_read_kernel_ehdr(kd) < 0)
goto failed;
- if (strncmp(mf, _PATH_FWMEM, strlen(_PATH_FWMEM)) == 0)
+ if (strncmp(mf, _PATH_FWMEM, strlen(_PATH_FWMEM)) == 0 ||
+ strncmp(mf, _PATH_DEVVMM, strlen(_PATH_DEVVMM)) == 0) {
kd->rawdump = 1;
+ kd->writable = 1;
+ }
SET_FOREACH(parch, kvm_arch) {
if ((*parch)->ka_probe(kd)) {
kd->arch = *parch;
@@ -405,6 +410,15 @@ ssize_t
kvm_write(kvm_t *kd, u_long kva, const void *buf, size_t len)
{
int cc;
+ ssize_t cw;
+ off_t pa;
+ const char *cp;
+
+ if (!ISALIVE(kd) && !kd->writable) {
+ _kvm_err(kd, kd->program,
+ "kvm_write not implemented for dead kernels");
+ return (-1);
+ }
if (ISALIVE(kd)) {
/*
@@ -422,12 +436,38 @@ kvm_write(kvm_t *kd, u_long kva, const v
} else if ((size_t)cc < len)
_kvm_err(kd, kd->program, "short write");
return (cc);
- } else {
- _kvm_err(kd, kd->program,
- "kvm_write not implemented for dead kernels");
- return (-1);
}
- /* NOTREACHED */
+
+ cp = buf;
+ while (len > 0) {
+ cc = kd->arch->ka_kvatop(kd, kva, &pa);
+ if (cc == 0)
+ return (-1);
+ if (cc > (ssize_t)len)
+ cc = len;
+ errno = 0;
+ if (lseek(kd->pmfd, pa, 0) == -1 && errno != 0) {
+ _kvm_syserr(kd, 0, _PATH_MEM);
+ break;
+ }
+ cw = write(kd->pmfd, cp, cc);
+ if (cw < 0) {
+ _kvm_syserr(kd, kd->program, "kvm_write");
+ break;
+ }
+ /*
+ * If ka_kvatop returns a bogus value or our core file is
+ * truncated, we might wind up seeking beyond the end of the
+ * core file in which case the read will return 0 (EOF).
+ */
+ if (cw == 0)
+ break;
+ cp += cw;
+ kva += cw;
+ len -= cw;
+ }
+
+ return (cp - (char *)buf);
}
int
Modified: head/lib/libkvm/kvm_private.h
==============================================================================
--- head/lib/libkvm/kvm_private.h Tue Dec 27 09:40:07 2016 (r310629)
+++ head/lib/libkvm/kvm_private.h Tue Dec 27 10:17:56 2016 (r310630)
@@ -78,6 +78,7 @@ struct __kvm {
*/
struct vmstate *vmst;
int rawdump; /* raw dump format */
+ int writable; /* physical memory is writable */
int vnet_initialized; /* vnet fields set up */
kvaddr_t vnet_start; /* start of kernel's vnet region */
More information about the svn-src-all
mailing list