diff options
| -rw-r--r-- | arch/x86/include/asm/xen/page.h | 16 | ||||
| -rw-r--r-- | arch/x86/xen/Makefile | 3 | ||||
| -rw-r--r-- | arch/x86/xen/mmu.c | 365 | ||||
| -rw-r--r-- | arch/x86/xen/p2m.c | 510 | ||||
| -rw-r--r-- | drivers/xen/Kconfig | 9 | ||||
| -rw-r--r-- | drivers/xen/Makefile | 2 | ||||
| -rw-r--r-- | drivers/xen/gntdev.c | 665 | ||||
| -rw-r--r-- | drivers/xen/grant-table.c | 46 | ||||
| -rw-r--r-- | include/xen/gntdev.h | 119 | ||||
| -rw-r--r-- | include/xen/grant_table.h | 44 |
10 files changed, 1408 insertions, 371 deletions
diff --git a/arch/x86/include/asm/xen/page.h b/arch/x86/include/asm/xen/page.h index 8760cc60a21c..f25bdf238a33 100644 --- a/arch/x86/include/asm/xen/page.h +++ b/arch/x86/include/asm/xen/page.h | |||
| @@ -42,6 +42,11 @@ extern unsigned int machine_to_phys_order; | |||
| 42 | extern unsigned long get_phys_to_machine(unsigned long pfn); | 42 | extern unsigned long get_phys_to_machine(unsigned long pfn); |
| 43 | extern bool set_phys_to_machine(unsigned long pfn, unsigned long mfn); | 43 | extern bool set_phys_to_machine(unsigned long pfn, unsigned long mfn); |
| 44 | 44 | ||
| 45 | extern int m2p_add_override(unsigned long mfn, struct page *page); | ||
| 46 | extern int m2p_remove_override(struct page *page); | ||
| 47 | extern struct page *m2p_find_override(unsigned long mfn); | ||
| 48 | extern unsigned long m2p_find_override_pfn(unsigned long mfn, unsigned long pfn); | ||
| 49 | |||
| 45 | static inline unsigned long pfn_to_mfn(unsigned long pfn) | 50 | static inline unsigned long pfn_to_mfn(unsigned long pfn) |
| 46 | { | 51 | { |
| 47 | unsigned long mfn; | 52 | unsigned long mfn; |
| @@ -72,9 +77,6 @@ static inline unsigned long mfn_to_pfn(unsigned long mfn) | |||
| 72 | if (xen_feature(XENFEAT_auto_translated_physmap)) | 77 | if (xen_feature(XENFEAT_auto_translated_physmap)) |
| 73 | return mfn; | 78 | return mfn; |
| 74 | 79 | ||
| 75 | if (unlikely((mfn >> machine_to_phys_order) != 0)) | ||
| 76 | return ~0; | ||
| 77 | |||
| 78 | pfn = 0; | 80 | pfn = 0; |
| 79 | /* | 81 | /* |
| 80 | * The array access can fail (e.g., device space beyond end of RAM). | 82 | * The array access can fail (e.g., device space beyond end of RAM). |
| @@ -83,6 +85,14 @@ static inline unsigned long mfn_to_pfn(unsigned long mfn) | |||
| 83 | */ | 85 | */ |
| 84 | __get_user(pfn, &machine_to_phys_mapping[mfn]); | 86 | __get_user(pfn, &machine_to_phys_mapping[mfn]); |
| 85 | 87 | ||
| 88 | /* | ||
| 89 | * If this appears to be a foreign mfn (because the pfn | ||
| 90 | * doesn't map back to the mfn), then check the local override | ||
| 91 | * table to see if there's a better pfn to use. | ||
| 92 | */ | ||
| 93 | if (get_phys_to_machine(pfn) != mfn) | ||
| 94 | pfn = m2p_find_override_pfn(mfn, pfn); | ||
| 95 | |||
| 86 | return pfn; | 96 | return pfn; |
| 87 | } | 97 | } |
| 88 | 98 | ||
diff --git a/arch/x86/xen/Makefile b/arch/x86/xen/Makefile index 779385158915..17c565de3d64 100644 --- a/arch/x86/xen/Makefile +++ b/arch/x86/xen/Makefile | |||
| @@ -12,7 +12,8 @@ CFLAGS_mmu.o := $(nostackp) | |||
| 12 | 12 | ||
| 13 | obj-y := enlighten.o setup.o multicalls.o mmu.o irq.o \ | 13 | obj-y := enlighten.o setup.o multicalls.o mmu.o irq.o \ |
| 14 | time.o xen-asm.o xen-asm_$(BITS).o \ | 14 | time.o xen-asm.o xen-asm_$(BITS).o \ |
| 15 | grant-table.o suspend.o platform-pci-unplug.o | 15 | grant-table.o suspend.o platform-pci-unplug.o \ |
| 16 | p2m.o | ||
| 16 | 17 | ||
| 17 | obj-$(CONFIG_SMP) += smp.o | 18 | obj-$(CONFIG_SMP) += smp.o |
| 18 | obj-$(CONFIG_PARAVIRT_SPINLOCKS)+= spinlock.o | 19 | obj-$(CONFIG_PARAVIRT_SPINLOCKS)+= spinlock.o |
diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c index 44924e551fde..7575e55cd52e 100644 --- a/arch/x86/xen/mmu.c +++ b/arch/x86/xen/mmu.c | |||
| @@ -173,371 +173,6 @@ DEFINE_PER_CPU(unsigned long, xen_current_cr3); /* actual vcpu cr3 */ | |||
| 173 | */ | 173 | */ |
| 174 | #define USER_LIMIT ((STACK_TOP_MAX + PGDIR_SIZE - 1) & PGDIR_MASK) | 174 | #define USER_LIMIT ((STACK_TOP_MAX + PGDIR_SIZE - 1) & PGDIR_MASK) |
| 175 | 175 | ||
| 176 | /* | ||
| 177 | * Xen leaves the responsibility for maintaining p2m mappings to the | ||
| 178 | * guests themselves, but it must also access and update the p2m array | ||
| 179 | * during suspend/resume when all the pages are reallocated. | ||
| 180 | * | ||
| 181 | * The p2m table is logically a flat array, but we implement it as a | ||
| 182 | * three-level tree to allow the address space to be sparse. | ||
| 183 | * | ||
| 184 | * Xen | ||
| 185 | * | | ||
| 186 | * p2m_top p2m_top_mfn | ||
| 187 | * / \ / \ | ||
| 188 | * p2m_mid p2m_mid p2m_mid_mfn p2m_mid_mfn | ||
| 189 | * / \ / \ / / | ||
| 190 | * p2m p2m p2m p2m p2m p2m p2m ... | ||
| 191 | * | ||
| 192 | * The p2m_mid_mfn pages are mapped by p2m_top_mfn_p. | ||
| 193 | * | ||
| 194 | * The p2m_top and p2m_top_mfn levels are limited to 1 page, so the | ||
| 195 | * maximum representable pseudo-physical address space is: | ||
| 196 | * P2M_TOP_PER_PAGE * P2M_MID_PER_PAGE * P2M_PER_PAGE pages | ||
| 197 | * | ||
| 198 | * P2M_PER_PAGE depends on the architecture, as a mfn is always | ||
| 199 | * unsigned long (8 bytes on 64-bit, 4 bytes on 32), leading to | ||
| 200 | * 512 and 1024 entries respectively. | ||
| 201 | */ | ||
| 202 | |||
| 203 | unsigned long xen_max_p2m_pfn __read_mostly; | ||
| 204 | |||
| 205 | #define P2M_PER_PAGE (PAGE_SIZE / sizeof(unsigned long)) | ||
| 206 | #define P2M_MID_PER_PAGE (PAGE_SIZE / sizeof(unsigned long *)) | ||
| 207 | #define P2M_TOP_PER_PAGE (PAGE_SIZE / sizeof(unsigned long **)) | ||
| 208 | |||
| 209 | #define MAX_P2M_PFN (P2M_TOP_PER_PAGE * P2M_MID_PER_PAGE * P2M_PER_PAGE) | ||
| 210 | |||
| 211 | /* Placeholders for holes in the address space */ | ||
| 212 | static RESERVE_BRK_ARRAY(unsigned long, p2m_missing, P2M_PER_PAGE); | ||
| 213 | static RESERVE_BRK_ARRAY(unsigned long *, p2m_mid_missing, P2M_MID_PER_PAGE); | ||
| 214 | static RESERVE_BRK_ARRAY(unsigned long, p2m_mid_missing_mfn, P2M_MID_PER_PAGE); | ||
| 215 | |||
| 216 | static RESERVE_BRK_ARRAY(unsigned long **, p2m_top, P2M_TOP_PER_PAGE); | ||
| 217 | static RESERVE_BRK_ARRAY(unsigned long, p2m_top_mfn, P2M_TOP_PER_PAGE); | ||
| 218 | static RESERVE_BRK_ARRAY(unsigned long *, p2m_top_mfn_p, P2M_TOP_PER_PAGE); | ||
| 219 | |||
| 220 | RESERVE_BRK(p2m_mid, PAGE_SIZE * (MAX_DOMAIN_PAGES / (P2M_PER_PAGE * P2M_MID_PER_PAGE))); | ||
| 221 | RESERVE_BRK(p2m_mid_mfn, PAGE_SIZE * (MAX_DOMAIN_PAGES / (P2M_PER_PAGE * P2M_MID_PER_PAGE))); | ||
| 222 | |||
| 223 | static inline unsigned p2m_top_index(unsigned long pfn) | ||
| 224 | { | ||
| 225 | BUG_ON(pfn >= MAX_P2M_PFN); | ||
| 226 | return pfn / (P2M_MID_PER_PAGE * P2M_PER_PAGE); | ||
| 227 | } | ||
| 228 | |||
| 229 | static inline unsigned p2m_mid_index(unsigned long pfn) | ||
| 230 | { | ||
| 231 | return (pfn / P2M_PER_PAGE) % P2M_MID_PER_PAGE; | ||
| 232 | } | ||
| 233 | |||
| 234 | static inline unsigned p2m_index(unsigned long pfn) | ||
| 235 | { | ||
| 236 | return pfn % P2M_PER_PAGE; | ||
| 237 | } | ||
| 238 | |||
| 239 | static void p2m_top_init(unsigned long ***top) | ||
| 240 | { | ||
| 241 | unsigned i; | ||
| 242 | |||
| 243 | for (i = 0; i < P2M_TOP_PER_PAGE; i++) | ||
| 244 | top[i] = p2m_mid_missing; | ||
| 245 | } | ||
| 246 | |||
| 247 | static void p2m_top_mfn_init(unsigned long *top) | ||
| 248 | { | ||
| 249 | unsigned i; | ||
| 250 | |||
| 251 | for (i = 0; i < P2M_TOP_PER_PAGE; i++) | ||
| 252 | top[i] = virt_to_mfn(p2m_mid_missing_mfn); | ||
| 253 | } | ||
| 254 | |||
| 255 | static void p2m_top_mfn_p_init(unsigned long **top) | ||
| 256 | { | ||
| 257 | unsigned i; | ||
| 258 | |||
| 259 | for (i = 0; i < P2M_TOP_PER_PAGE; i++) | ||
| 260 | top[i] = p2m_mid_missing_mfn; | ||
| 261 | } | ||
| 262 | |||
| 263 | static void p2m_mid_init(unsigned long **mid) | ||
| 264 | { | ||
| 265 | unsigned i; | ||
| 266 | |||
| 267 | for (i = 0; i < P2M_MID_PER_PAGE; i++) | ||
| 268 | mid[i] = p2m_missing; | ||
| 269 | } | ||
| 270 | |||
| 271 | static void p2m_mid_mfn_init(unsigned long *mid) | ||
| 272 | { | ||
| 273 | unsigned i; | ||
| 274 | |||
| 275 | for (i = 0; i < P2M_MID_PER_PAGE; i++) | ||
| 276 | mid[i] = virt_to_mfn(p2m_missing); | ||
| 277 | } | ||
| 278 | |||
| 279 | static void p2m_init(unsigned long *p2m) | ||
| 280 | { | ||
| 281 | unsigned i; | ||
| 282 | |||
| 283 | for (i = 0; i < P2M_MID_PER_PAGE; i++) | ||
| 284 | p2m[i] = INVALID_P2M_ENTRY; | ||
| 285 | } | ||
| 286 | |||
| 287 | /* | ||
| 288 | * Build the parallel p2m_top_mfn and p2m_mid_mfn structures | ||
| 289 | * | ||
| 290 | * This is called both at boot time, and after resuming from suspend: | ||
| 291 | * - At boot time we're called very early, and must use extend_brk() | ||
| 292 | * to allocate memory. | ||
| 293 | * | ||
| 294 | * - After resume we're called from within stop_machine, but the mfn | ||
| 295 | * tree should alreay be completely allocated. | ||
| 296 | */ | ||
| 297 | void xen_build_mfn_list_list(void) | ||
| 298 | { | ||
| 299 | unsigned long pfn; | ||
| 300 | |||
| 301 | /* Pre-initialize p2m_top_mfn to be completely missing */ | ||
