|
27 | 27 | #include <linux/srcu.h>
|
28 | 28 | #include <linux/anon_inodes.h>
|
29 | 29 | #include <linux/file.h>
|
| 30 | +#include <linux/debugfs.h> |
30 | 31 |
|
31 | 32 | #include <asm/tlbflush.h>
|
32 | 33 | #include <asm/kvm_ppc.h>
|
@@ -1490,6 +1491,141 @@ int kvm_vm_ioctl_get_htab_fd(struct kvm *kvm, struct kvm_get_htab_fd *ghf)
|
1490 | 1491 | return ret;
|
1491 | 1492 | }
|
1492 | 1493 |
|
| 1494 | +struct debugfs_htab_state { |
| 1495 | + struct kvm *kvm; |
| 1496 | + struct mutex mutex; |
| 1497 | + unsigned long hpt_index; |
| 1498 | + int chars_left; |
| 1499 | + int buf_index; |
| 1500 | + char buf[64]; |
| 1501 | +}; |
| 1502 | + |
| 1503 | +static int debugfs_htab_open(struct inode *inode, struct file *file) |
| 1504 | +{ |
| 1505 | + struct kvm *kvm = inode->i_private; |
| 1506 | + struct debugfs_htab_state *p; |
| 1507 | + |
| 1508 | + p = kzalloc(sizeof(*p), GFP_KERNEL); |
| 1509 | + if (!p) |
| 1510 | + return -ENOMEM; |
| 1511 | + |
| 1512 | + kvm_get_kvm(kvm); |
| 1513 | + p->kvm = kvm; |
| 1514 | + mutex_init(&p->mutex); |
| 1515 | + file->private_data = p; |
| 1516 | + |
| 1517 | + return nonseekable_open(inode, file); |
| 1518 | +} |
| 1519 | + |
| 1520 | +static int debugfs_htab_release(struct inode *inode, struct file *file) |
| 1521 | +{ |
| 1522 | + struct debugfs_htab_state *p = file->private_data; |
| 1523 | + |
| 1524 | + kvm_put_kvm(p->kvm); |
| 1525 | + kfree(p); |
| 1526 | + return 0; |
| 1527 | +} |
| 1528 | + |
| 1529 | +static ssize_t debugfs_htab_read(struct file *file, char __user *buf, |
| 1530 | + size_t len, loff_t *ppos) |
| 1531 | +{ |
| 1532 | + struct debugfs_htab_state *p = file->private_data; |
| 1533 | + ssize_t ret, r; |
| 1534 | + unsigned long i, n; |
| 1535 | + unsigned long v, hr, gr; |
| 1536 | + struct kvm *kvm; |
| 1537 | + __be64 *hptp; |
| 1538 | + |
| 1539 | + ret = mutex_lock_interruptible(&p->mutex); |
| 1540 | + if (ret) |
| 1541 | + return ret; |
| 1542 | + |
| 1543 | + if (p->chars_left) { |
| 1544 | + n = p->chars_left; |
| 1545 | + if (n > len) |
| 1546 | + n = len; |
| 1547 | + r = copy_to_user(buf, p->buf + p->buf_index, n); |
| 1548 | + n -= r; |
| 1549 | + p->chars_left -= n; |
| 1550 | + p->buf_index += n; |
| 1551 | + buf += n; |
| 1552 | + len -= n; |
| 1553 | + ret = n; |
| 1554 | + if (r) { |
| 1555 | + if (!n) |
| 1556 | + ret = -EFAULT; |
| 1557 | + goto out; |
| 1558 | + } |
| 1559 | + } |
| 1560 | + |
| 1561 | + kvm = p->kvm; |
| 1562 | + i = p->hpt_index; |
| 1563 | + hptp = (__be64 *)(kvm->arch.hpt_virt + (i * HPTE_SIZE)); |
| 1564 | + for (; len != 0 && i < kvm->arch.hpt_npte; ++i, hptp += 2) { |
| 1565 | + if (!(be64_to_cpu(hptp[0]) & (HPTE_V_VALID | HPTE_V_ABSENT))) |
| 1566 | + continue; |
| 1567 | + |
| 1568 | + /* lock the HPTE so it's stable and read it */ |
| 1569 | + preempt_disable(); |
| 1570 | + while (!try_lock_hpte(hptp, HPTE_V_HVLOCK)) |
| 1571 | + cpu_relax(); |
| 1572 | + v = be64_to_cpu(hptp[0]) & ~HPTE_V_HVLOCK; |
| 1573 | + hr = be64_to_cpu(hptp[1]); |
| 1574 | + gr = kvm->arch.revmap[i].guest_rpte; |
| 1575 | + unlock_hpte(hptp, v); |
| 1576 | + preempt_enable(); |
| 1577 | + |
| 1578 | + if (!(v & (HPTE_V_VALID | HPTE_V_ABSENT))) |
| 1579 | + continue; |
| 1580 | + |
| 1581 | + n = scnprintf(p->buf, sizeof(p->buf), |
| 1582 | + "%6lx %.16lx %.16lx %.16lx\n", |
| 1583 | + i, v, hr, gr); |
| 1584 | + p->chars_left = n; |
| 1585 | + if (n > len) |
| 1586 | + n = len; |
| 1587 | + r = copy_to_user(buf, p->buf, n); |
| 1588 | + n -= r; |
| 1589 | + p->chars_left -= n; |
| 1590 | + p->buf_index = n; |
| 1591 | + buf += n; |
| 1592 | + len -= n; |
| 1593 | + ret += n; |
| 1594 | + if (r) { |
| 1595 | + if (!ret) |
| 1596 | + ret = -EFAULT; |
| 1597 | + goto out; |
| 1598 | + } |
| 1599 | + } |
| 1600 | + p->hpt_index = i; |
| 1601 | + |
| 1602 | + out: |
| 1603 | + mutex_unlock(&p->mutex); |
| 1604 | + return ret; |
| 1605 | +} |
| 1606 | + |
| 1607 | +ssize_t debugfs_htab_write(struct file *file, const char __user *buf, |
| 1608 | + size_t len, loff_t *ppos) |
| 1609 | +{ |
| 1610 | + return -EACCES; |
| 1611 | +} |
| 1612 | + |
| 1613 | +static const struct file_operations debugfs_htab_fops = { |
| 1614 | + .owner = THIS_MODULE, |
| 1615 | + .open = debugfs_htab_open, |
| 1616 | + .release = debugfs_htab_release, |
| 1617 | + .read = debugfs_htab_read, |
| 1618 | + .write = debugfs_htab_write, |
| 1619 | + .llseek = generic_file_llseek, |
| 1620 | +}; |
| 1621 | + |
| 1622 | +void kvmppc_mmu_debugfs_init(struct kvm *kvm) |
| 1623 | +{ |
| 1624 | + kvm->arch.htab_dentry = debugfs_create_file("htab", 0400, |
| 1625 | + kvm->arch.debugfs_dir, kvm, |
| 1626 | + &debugfs_htab_fops); |
| 1627 | +} |
| 1628 | + |
1493 | 1629 | void kvmppc_mmu_book3s_hv_init(struct kvm_vcpu *vcpu)
|
1494 | 1630 | {
|
1495 | 1631 | struct kvmppc_mmu *mmu = &vcpu->arch.mmu;
|
|
0 commit comments