Revision e68cb8b4
b/hw/ppc/spapr.c | ||
---|---|---|
735 | 735 |
{ |
736 | 736 |
sPAPREnvironment *spapr = opaque; |
737 | 737 |
|
738 |
spapr->htab_save_index = 0; |
|
739 |
spapr->htab_first_pass = true; |
|
740 |
|
|
741 | 738 |
/* "Iteration" header */ |
742 | 739 |
qemu_put_be32(f, spapr->htab_shift); |
743 | 740 |
|
741 |
if (spapr->htab) { |
|
742 |
spapr->htab_save_index = 0; |
|
743 |
spapr->htab_first_pass = true; |
|
744 |
} else { |
|
745 |
assert(kvm_enabled()); |
|
746 |
|
|
747 |
spapr->htab_fd = kvmppc_get_htab_fd(false); |
|
748 |
if (spapr->htab_fd < 0) { |
|
749 |
fprintf(stderr, "Unable to open fd for reading hash table from KVM: %s\n", |
|
750 |
strerror(errno)); |
|
751 |
return -1; |
|
752 |
} |
|
753 |
} |
|
754 |
|
|
755 |
|
|
744 | 756 |
return 0; |
745 | 757 |
} |
746 | 758 |
|
747 |
#define MAX_ITERATION_NS 5000000 /* 5 ms */ |
|
748 |
|
|
749 | 759 |
static void htab_save_first_pass(QEMUFile *f, sPAPREnvironment *spapr, |
750 | 760 |
int64_t max_ns) |
751 | 761 |
{ |
... | ... | |
796 | 806 |
spapr->htab_save_index = index; |
797 | 807 |
} |
798 | 808 |
|
799 |
static bool htab_save_later_pass(QEMUFile *f, sPAPREnvironment *spapr,
|
|
800 |
int64_t max_ns)
|
|
809 |
static int htab_save_later_pass(QEMUFile *f, sPAPREnvironment *spapr,
|
|
810 |
int64_t max_ns) |
|
801 | 811 |
{ |
802 | 812 |
bool final = max_ns < 0; |
803 | 813 |
int htabslots = HTAB_SIZE(spapr) / HASH_PTE_SIZE_64; |
... | ... | |
870 | 880 |
|
871 | 881 |
spapr->htab_save_index = index; |
872 | 882 |
|
873 |
return (examined >= htabslots) && (sent == 0); |
|
883 |
return (examined >= htabslots) && (sent == 0) ? 1 : 0;
|
|
874 | 884 |
} |
875 | 885 |
|
886 |
#define MAX_ITERATION_NS 5000000 /* 5 ms */ |
|
887 |
#define MAX_KVM_BUF_SIZE 2048 |
|
888 |
|
|
876 | 889 |
static int htab_save_iterate(QEMUFile *f, void *opaque) |
877 | 890 |
{ |
878 | 891 |
sPAPREnvironment *spapr = opaque; |
879 |
bool nothingleft = false;;
|
|
892 |
int rc = 0;
|
|
880 | 893 |
|
881 | 894 |
/* Iteration header */ |
882 | 895 |
qemu_put_be32(f, 0); |
883 | 896 |
|
884 |
if (spapr->htab_first_pass) { |
|
897 |
if (!spapr->htab) { |
|
898 |
assert(kvm_enabled()); |
|
899 |
|
|
900 |
rc = kvmppc_save_htab(f, spapr->htab_fd, |
|
901 |
MAX_KVM_BUF_SIZE, MAX_ITERATION_NS); |
|
902 |
if (rc < 0) { |
|
903 |
return rc; |
|
904 |
} |
|
905 |
} else if (spapr->htab_first_pass) { |
|
885 | 906 |
htab_save_first_pass(f, spapr, MAX_ITERATION_NS); |
886 | 907 |
} else { |
887 |
nothingleft = htab_save_later_pass(f, spapr, MAX_ITERATION_NS);
|
|
908 |
rc = htab_save_later_pass(f, spapr, MAX_ITERATION_NS);
|
|
888 | 909 |
} |
889 | 910 |
|
890 | 911 |
/* End marker */ |
... | ... | |
892 | 913 |
qemu_put_be16(f, 0); |
893 | 914 |
qemu_put_be16(f, 0); |
894 | 915 |
|
895 |
return nothingleft ? 1 : 0;
|
|
916 |
return rc;
|
|
896 | 917 |
} |
897 | 918 |
|
898 | 919 |
static int htab_save_complete(QEMUFile *f, void *opaque) |
... | ... | |
902 | 923 |
/* Iteration header */ |
903 | 924 |
qemu_put_be32(f, 0); |
904 | 925 |
|
905 |
htab_save_later_pass(f, spapr, -1); |
|
926 |
if (!spapr->htab) { |
|
927 |
int rc; |
|
928 |
|
|
929 |
assert(kvm_enabled()); |
|
930 |
|
|
931 |
rc = kvmppc_save_htab(f, spapr->htab_fd, MAX_KVM_BUF_SIZE, -1); |
|
932 |
if (rc < 0) { |
|
933 |
return rc; |
|
934 |
} |
|
935 |
close(spapr->htab_fd); |
|
936 |
spapr->htab_fd = -1; |
|
937 |
} else { |
|
938 |
htab_save_later_pass(f, spapr, -1); |
|
939 |
} |
|
906 | 940 |
|
907 | 941 |
/* End marker */ |
908 | 942 |
qemu_put_be32(f, 0); |
... | ... | |
916 | 950 |
{ |
917 | 951 |
sPAPREnvironment *spapr = opaque; |
918 | 952 |
uint32_t section_hdr; |
953 |
int fd = -1; |
|
919 | 954 |
|
920 | 955 |
if (version_id < 1 || version_id > 1) { |
921 | 956 |
fprintf(stderr, "htab_load() bad version\n"); |
... | ... | |
932 | 967 |
return 0; |
933 | 968 |
} |
934 | 969 |
|
970 |
if (!spapr->htab) { |
|
971 |
assert(kvm_enabled()); |
|
972 |
|
|
973 |
fd = kvmppc_get_htab_fd(true); |
|
974 |
if (fd < 0) { |
|
975 |
fprintf(stderr, "Unable to open fd to restore KVM hash table: %s\n", |
|
976 |
strerror(errno)); |
|
977 |
} |
|
978 |
} |
|
979 |
|
|
935 | 980 |
while (true) { |
936 | 981 |
uint32_t index; |
937 | 982 |
uint16_t n_valid, n_invalid; |
... | ... | |
945 | 990 |
break; |
946 | 991 |
} |
947 | 992 |
|
948 |
if ((index + n_valid + n_invalid) >=
|
|
993 |
if ((index + n_valid + n_invalid) > |
|
949 | 994 |
(HTAB_SIZE(spapr) / HASH_PTE_SIZE_64)) { |
950 | 995 |
/* Bad index in stream */ |
951 | 996 |
fprintf(stderr, "htab_load() bad index %d (%hd+%hd entries) " |
952 |
"in htab stream\n", index, n_valid, n_invalid); |
|
997 |
"in htab stream (htab_shift=%d)\n", index, n_valid, n_invalid, |
|
998 |
spapr->htab_shift); |
|
953 | 999 |
return -EINVAL; |
954 | 1000 |
} |
955 | 1001 |
|
956 |
if (n_valid) { |
|
957 |
qemu_get_buffer(f, HPTE(spapr->htab, index), |
|
958 |
HASH_PTE_SIZE_64 * n_valid); |
|
959 |
} |
|
960 |
if (n_invalid) { |
|
961 |
memset(HPTE(spapr->htab, index + n_valid), 0, |
|
962 |
HASH_PTE_SIZE_64 * n_invalid); |
|
1002 |
if (spapr->htab) { |
|
1003 |
if (n_valid) { |
|
1004 |
qemu_get_buffer(f, HPTE(spapr->htab, index), |
|
1005 |
HASH_PTE_SIZE_64 * n_valid); |
|
1006 |
} |
|
1007 |
if (n_invalid) { |
|
1008 |
memset(HPTE(spapr->htab, index + n_valid), 0, |
|
1009 |
HASH_PTE_SIZE_64 * n_invalid); |
|
1010 |
} |
|
1011 |
} else { |
|
1012 |
int rc; |
|
1013 |
|
|
1014 |
assert(fd >= 0); |
|
1015 |
|
|
1016 |
rc = kvmppc_load_htab_chunk(f, fd, index, n_valid, n_invalid); |
|
1017 |
if (rc < 0) { |
|
1018 |
return rc; |
|
1019 |
} |
|
963 | 1020 |
} |
964 | 1021 |
} |
965 | 1022 |
|
1023 |
if (!spapr->htab) { |
|
1024 |
assert(fd >= 0); |
|
1025 |
close(fd); |
|
1026 |
} |
|
1027 |
|
|
966 | 1028 |
return 0; |
967 | 1029 |
} |
968 | 1030 |
|
b/include/hw/ppc/spapr.h | ||
---|---|---|
37 | 37 |
/* Migration state */ |
38 | 38 |
int htab_save_index; |
39 | 39 |
bool htab_first_pass; |
40 |
int htab_fd; |
|
40 | 41 |
} sPAPREnvironment; |
41 | 42 |
|
42 | 43 |
#define H_SUCCESS 0 |
b/target-ppc/kvm.c | ||
---|---|---|
65 | 65 |
static int cap_epr; |
66 | 66 |
static int cap_ppc_watchdog; |
67 | 67 |
static int cap_papr; |
68 |
static int cap_htab_fd; |
|
68 | 69 |
|
69 | 70 |
/* XXX We have a race condition where we actually have a level triggered |
70 | 71 |
* interrupt, but the infrastructure can't expose that yet, so the guest |
... | ... | |
101 | 102 |
cap_ppc_watchdog = kvm_check_extension(s, KVM_CAP_PPC_BOOKE_WATCHDOG); |
102 | 103 |
/* Note: we don't set cap_papr here, because this capability is |
103 | 104 |
* only activated after this by kvmppc_set_papr() */ |
105 |
cap_htab_fd = kvm_check_extension(s, KVM_CAP_PPC_HTAB_FD); |
|
104 | 106 |
|
105 | 107 |
if (!cap_interrupt_level) { |
106 | 108 |
fprintf(stderr, "KVM: Couldn't find level irq capability. Expect the " |
... | ... | |
1788 | 1790 |
} |
1789 | 1791 |
|
1790 | 1792 |
|
1793 |
int kvmppc_get_htab_fd(bool write) |
|
1794 |
{ |
|
1795 |
struct kvm_get_htab_fd s = { |
|
1796 |
.flags = write ? KVM_GET_HTAB_WRITE : 0, |
|
1797 |
.start_index = 0, |
|
1798 |
}; |
|
1799 |
|
|
1800 |
if (!cap_htab_fd) { |
|
1801 |
fprintf(stderr, "KVM version doesn't support saving the hash table\n"); |
|
1802 |
return -1; |
|
1803 |
} |
|
1804 |
|
|
1805 |
return kvm_vm_ioctl(kvm_state, KVM_PPC_GET_HTAB_FD, &s); |
|
1806 |
} |
|
1807 |
|
|
1808 |
int kvmppc_save_htab(QEMUFile *f, int fd, size_t bufsize, int64_t max_ns) |
|
1809 |
{ |
|
1810 |
int64_t starttime = qemu_get_clock_ns(rt_clock); |
|
1811 |
uint8_t buf[bufsize]; |
|
1812 |
ssize_t rc; |
|
1813 |
|
|
1814 |
do { |
|
1815 |
rc = read(fd, buf, bufsize); |
|
1816 |
if (rc < 0) { |
|
1817 |
fprintf(stderr, "Error reading data from KVM HTAB fd: %s\n", |
|
1818 |
strerror(errno)); |
|
1819 |
return rc; |
|
1820 |
} else if (rc) { |
|
1821 |
/* Kernel already retuns data in BE format for the file */ |
|
1822 |
qemu_put_buffer(f, buf, rc); |
|
1823 |
} |
|
1824 |
} while ((rc != 0) |
|
1825 |
&& ((max_ns < 0) |
|
1826 |
|| ((qemu_get_clock_ns(rt_clock) - starttime) < max_ns))); |
|
1827 |
|
|
1828 |
return (rc == 0) ? 1 : 0; |
|
1829 |
} |
|
1830 |
|
|
1831 |
int kvmppc_load_htab_chunk(QEMUFile *f, int fd, uint32_t index, |
|
1832 |
uint16_t n_valid, uint16_t n_invalid) |
|
1833 |
{ |
|
1834 |
struct kvm_get_htab_header *buf; |
|
1835 |
size_t chunksize = sizeof(*buf) + n_valid*HASH_PTE_SIZE_64; |
|
1836 |
ssize_t rc; |
|
1837 |
|
|
1838 |
buf = alloca(chunksize); |
|
1839 |
/* This is KVM on ppc, so this is all big-endian */ |
|
1840 |
buf->index = index; |
|
1841 |
buf->n_valid = n_valid; |
|
1842 |
buf->n_invalid = n_invalid; |
|
1843 |
|
|
1844 |
qemu_get_buffer(f, (void *)(buf + 1), HASH_PTE_SIZE_64*n_valid); |
|
1845 |
|
|
1846 |
rc = write(fd, buf, chunksize); |
|
1847 |
if (rc < 0) { |
|
1848 |
fprintf(stderr, "Error writing KVM hash table: %s\n", |
|
1849 |
strerror(errno)); |
|
1850 |
return rc; |
|
1851 |
} |
|
1852 |
if (rc != chunksize) { |
|
1853 |
/* We should never get a short write on a single chunk */ |
|
1854 |
fprintf(stderr, "Short write, restoring KVM hash table\n"); |
|
1855 |
return -1; |
|
1856 |
} |
|
1857 |
return 0; |
|
1858 |
} |
|
1859 |
|
|
1791 | 1860 |
bool kvm_arch_stop_on_emulation_error(CPUState *cpu) |
1792 | 1861 |
{ |
1793 | 1862 |
return true; |
b/target-ppc/kvm_ppc.h | ||
---|---|---|
38 | 38 |
#endif /* !CONFIG_USER_ONLY */ |
39 | 39 |
int kvmppc_fixup_cpu(PowerPCCPU *cpu); |
40 | 40 |
bool kvmppc_has_cap_epr(void); |
41 |
int kvmppc_get_htab_fd(bool write); |
|
42 |
int kvmppc_save_htab(QEMUFile *f, int fd, size_t bufsize, int64_t max_ns); |
|
43 |
int kvmppc_load_htab_chunk(QEMUFile *f, int fd, uint32_t index, |
|
44 |
uint16_t n_valid, uint16_t n_invalid); |
|
41 | 45 |
|
42 | 46 |
#else |
43 | 47 |
|
... | ... | |
159 | 163 |
{ |
160 | 164 |
return false; |
161 | 165 |
} |
166 |
|
|
167 |
static inline int kvmppc_get_htab_fd(bool write) |
|
168 |
{ |
|
169 |
return -1; |
|
170 |
} |
|
171 |
|
|
172 |
static inline int kvmppc_save_htab(QEMUFile *f, int fd, size_t bufsize, |
|
173 |
int64_t max_ns) |
|
174 |
{ |
|
175 |
abort(); |
|
176 |
} |
|
177 |
|
|
178 |
static inline int kvmppc_load_htab_chunk(QEMUFile *f, int fd, uint32_t index, |
|
179 |
uint16_t n_valid, uint16_t n_invalid) |
|
180 |
{ |
|
181 |
abort(); |
|
182 |
} |
|
183 |
|
|
162 | 184 |
#endif |
163 | 185 |
|
164 | 186 |
#ifndef CONFIG_KVM |
Also available in: Unified diff