diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2015-04-16 15:01:03 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2015-04-16 15:01:03 -0400 |
commit | 497a5df7bf6ffd136ae21c49d1a01292930d7ca2 (patch) | |
tree | 774215d43cdc9fbd8660086d1801400163dcbd52 /arch/x86/xen | |
parent | 714d8e7e27197dd39b2550e762a6a6fcf397a471 (diff) | |
parent | 0b97b03d88b40bfbd7ff0e069186a137d9786d43 (diff) |
Merge tag 'stable/for-linus-4.1-rc0-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/xen/tip
Pull xen features and fixes from David Vrabel:
- use a single source list of hypercalls, generating other tables etc.
at build time.
- add a "Xen PV" APIC driver to support >255 VCPUs in PV guests.
- significant performance improve to guest save/restore/migration.
- scsiback/front save/restore support.
- infrastructure for multi-page xenbus rings.
- misc fixes.
* tag 'stable/for-linus-4.1-rc0-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/xen/tip:
xen/pci: Try harder to get PXM information for Xen
xenbus_client: Extend interface to support multi-page ring
xen-pciback: also support disabling of bus-mastering and memory-write-invalidate
xen: support suspend/resume in pvscsi frontend
xen: scsiback: add LUN of restored domain
xen-scsiback: define a pr_fmt macro with xen-pvscsi
xen/mce: fix up xen_late_init_mcelog() error handling
xen/privcmd: improve performance of MMAPBATCH_V2
xen: unify foreign GFN map/unmap for auto-xlated physmap guests
x86/xen/apic: WARN with details.
x86/xen: Provide a "Xen PV" APIC driver to support >255 VCPUs
xen/pciback: Don't print scary messages when unsupported by hypervisor.
xen: use generated hypercall symbols in arch/x86/xen/xen-head.S
xen: use generated hypervisor symbols in arch/x86/xen/trace.c
xen: synchronize include/xen/interface/xen.h with xen
xen: build infrastructure for generating hypercall depending symbols
xen: balloon: Use static attribute groups for sysfs entries
xen: pcpu: Use static attribute groups for sysfs entry
Diffstat (limited to 'arch/x86/xen')
-rw-r--r-- | arch/x86/xen/apic.c | 180 | ||||
-rw-r--r-- | arch/x86/xen/enlighten.c | 90 | ||||
-rw-r--r-- | arch/x86/xen/mmu.c | 207 | ||||
-rw-r--r-- | arch/x86/xen/trace.c | 50 | ||||
-rw-r--r-- | arch/x86/xen/xen-head.S | 63 |
5 files changed, 278 insertions, 312 deletions
diff --git a/arch/x86/xen/apic.c b/arch/x86/xen/apic.c index 7005ced5d1ad..70e060ad879a 100644 --- a/arch/x86/xen/apic.c +++ b/arch/x86/xen/apic.c | |||
@@ -7,6 +7,7 @@ | |||
7 | #include <xen/xen.h> | 7 | #include <xen/xen.h> |
8 | #include <xen/interface/physdev.h> | 8 | #include <xen/interface/physdev.h> |
9 | #include "xen-ops.h" | 9 | #include "xen-ops.h" |
10 | #include "smp.h" | ||
10 | 11 | ||
11 | static unsigned int xen_io_apic_read(unsigned apic, unsigned reg) | 12 | static unsigned int xen_io_apic_read(unsigned apic, unsigned reg) |
12 | { | 13 | { |
@@ -28,7 +29,186 @@ static unsigned int xen_io_apic_read(unsigned apic, unsigned reg) | |||
28 | return 0xfd; | 29 | return 0xfd; |
29 | } | 30 | } |
30 | 31 | ||
32 | static unsigned long xen_set_apic_id(unsigned int x) | ||
33 | { | ||
34 | WARN_ON(1); | ||
35 | return x; | ||
36 | } | ||
37 | |||
38 | static unsigned int xen_get_apic_id(unsigned long x) | ||
39 | { | ||
40 | return ((x)>>24) & 0xFFu; | ||
41 | } | ||
42 | |||
43 | static u32 xen_apic_read(u32 reg) | ||
44 | { | ||
45 | struct xen_platform_op op = { | ||
46 | .cmd = XENPF_get_cpuinfo, | ||
47 | .interface_version = XENPF_INTERFACE_VERSION, | ||
48 | .u.pcpu_info.xen_cpuid = 0, | ||
49 | }; | ||
50 | int ret = 0; | ||
51 | |||
52 | /* Shouldn't need this as APIC is turned off for PV, and we only | ||
53 | * get called on the bootup processor. But just in case. */ | ||
54 | if (!xen_initial_domain() || smp_processor_id()) | ||
55 | return 0; | ||
56 | |||
57 | if (reg == APIC_LVR) | ||
58 | return 0x10; | ||
59 | #ifdef CONFIG_X86_32 | ||
60 | if (reg == APIC_LDR) | ||
61 | return SET_APIC_LOGICAL_ID(1UL << smp_processor_id()); | ||
62 | #endif | ||
63 | if (reg != APIC_ID) | ||
64 | return 0; | ||
65 | |||
66 | ret = HYPERVISOR_dom0_op(&op); | ||
67 | if (ret) | ||
68 | return 0; | ||
69 | |||
70 | return op.u.pcpu_info.apic_id << 24; | ||
71 | } | ||
72 | |||
73 | static void xen_apic_write(u32 reg, u32 val) | ||
74 | { | ||
75 | /* Warn to see if there's any stray references */ | ||
76 | WARN(1,"register: %x, value: %x\n", reg, val); | ||
77 | } | ||
78 | |||
79 | static u64 xen_apic_icr_read(void) | ||
80 | { | ||
81 | return 0; | ||
82 | } | ||
83 | |||
84 | static void xen_apic_icr_write(u32 low, u32 id) | ||
85 | { | ||
86 | /* Warn to see if there's any stray references */ | ||
87 | WARN_ON(1); | ||
88 | } | ||
89 | |||
90 | static u32 xen_safe_apic_wait_icr_idle(void) | ||
91 | { | ||
92 | return 0; | ||
93 | } | ||
94 | |||
95 | static int xen_apic_probe_pv(void) | ||
96 | { | ||
97 | if (xen_pv_domain()) | ||
98 | return 1; | ||
99 | |||
100 | return 0; | ||
101 | } | ||
102 | |||
103 | static int xen_madt_oem_check(char *oem_id, char *oem_table_id) | ||
104 | { | ||
105 | return xen_pv_domain(); | ||
106 | } | ||
107 | |||
108 | static int xen_id_always_valid(int apicid) | ||
109 | { | ||
110 | return 1; | ||
111 | } | ||
112 | |||
113 | static int xen_id_always_registered(void) | ||
114 | { | ||
115 | return 1; | ||
116 | } | ||
117 | |||
118 | static int xen_phys_pkg_id(int initial_apic_id, int index_msb) | ||
119 | { | ||
120 | return initial_apic_id >> index_msb; | ||
121 | } | ||
122 | |||
123 | #ifdef CONFIG_X86_32 | ||
124 | static int xen_x86_32_early_logical_apicid(int cpu) | ||
125 | { | ||
126 | /* Match with APIC_LDR read. Otherwise setup_local_APIC complains. */ | ||
127 | return 1 << cpu; | ||
128 | } | ||
129 | #endif | ||
130 | |||
131 | static void xen_noop(void) | ||
132 | { | ||
133 | } | ||
134 | |||
135 | static void xen_silent_inquire(int apicid) | ||
136 | { | ||
137 | } | ||
138 | |||
139 | static struct apic xen_pv_apic = { | ||
140 | .name = "Xen PV", | ||
141 | .probe = xen_apic_probe_pv, | ||
142 | .acpi_madt_oem_check = xen_madt_oem_check, | ||
143 | .apic_id_valid = xen_id_always_valid, | ||
144 | .apic_id_registered = xen_id_always_registered, | ||
145 | |||
146 | /* .irq_delivery_mode - used in native_compose_msi_msg only */ | ||
147 | /* .irq_dest_mode - used in native_compose_msi_msg only */ | ||
148 | |||
149 | .target_cpus = default_target_cpus, | ||
150 | .disable_esr = 0, | ||
151 | /* .dest_logical - default_send_IPI_ use it but we use our own. */ | ||
152 | .check_apicid_used = default_check_apicid_used, /* Used on 32-bit */ | ||
153 | |||
154 | .vector_allocation_domain = flat_vector_allocation_domain, | ||
155 | .init_apic_ldr = xen_noop, /* setup_local_APIC calls it */ | ||
156 | |||
157 | .ioapic_phys_id_map = default_ioapic_phys_id_map, /* Used on 32-bit */ | ||
158 | .setup_apic_routing = NULL, | ||
159 | .cpu_present_to_apicid = default_cpu_present_to_apicid, | ||
160 | .apicid_to_cpu_present = physid_set_mask_of_physid, /* Used on 32-bit */ | ||
161 | .check_phys_apicid_present = default_check_phys_apicid_present, /* smp_sanity_check needs it */ | ||
162 | .phys_pkg_id = xen_phys_pkg_id, /* detect_ht */ | ||
163 | |||
164 | .get_apic_id = xen_get_apic_id, | ||
165 | .set_apic_id = xen_set_apic_id, /* Can be NULL on 32-bit. */ | ||
166 | .apic_id_mask = 0xFF << 24, /* Used by verify_local_APIC. Match with what xen_get_apic_id does. */ | ||
167 | |||
168 | .cpu_mask_to_apicid_and = flat_cpu_mask_to_apicid_and, | ||
169 | |||
170 | #ifdef CONFIG_SMP | ||
171 | .send_IPI_mask = xen_send_IPI_mask, | ||
172 | .send_IPI_mask_allbutself = xen_send_IPI_mask_allbutself, | ||
173 | .send_IPI_allbutself = xen_send_IPI_allbutself, | ||
174 | .send_IPI_all = xen_send_IPI_all, | ||
175 | .send_IPI_self = xen_send_IPI_self, | ||
176 | #endif | ||
177 | /* .wait_for_init_deassert- used by AP bootup - smp_callin which we don't use */ | ||
178 | .inquire_remote_apic = xen_silent_inquire, | ||
179 | |||
180 | .read = xen_apic_read, | ||
181 | .write = xen_apic_write, | ||
182 | .eoi_write = xen_apic_write, | ||
183 | |||
184 | .icr_read = xen_apic_icr_read, | ||
185 | .icr_write = xen_apic_icr_write, | ||
186 | .wait_icr_idle = xen_noop, | ||
187 | .safe_wait_icr_idle = xen_safe_apic_wait_icr_idle, | ||
188 | |||
189 | #ifdef CONFIG_X86_32 | ||
190 | /* generic_processor_info and setup_local_APIC. */ | ||
191 | .x86_32_early_logical_apicid = xen_x86_32_early_logical_apicid, | ||
192 | #endif | ||
193 | }; | ||
194 | |||
195 | static void __init xen_apic_check(void) | ||
196 | { | ||
197 | if (apic == &xen_pv_apic) | ||
198 | return; | ||
199 | |||
200 | pr_info("Switched APIC routing from %s to %s.\n", apic->name, | ||
201 | xen_pv_apic.name); | ||
202 | apic = &xen_pv_apic; | ||
203 | } | ||
31 | void __init xen_init_apic(void) | 204 | void __init xen_init_apic(void) |
32 | { | 205 | { |
33 | x86_io_apic_ops.read = xen_io_apic_read; | 206 | x86_io_apic_ops.read = xen_io_apic_read; |
207 | /* On PV guests the APIC CPUID bit is disabled so none of the | ||
208 | * routines end up executing. */ | ||
209 | if (!xen_initial_domain()) | ||
210 | apic = &xen_pv_apic; | ||
211 | |||
212 | x86_platform.apic_post_init = xen_apic_check; | ||
34 | } | 213 | } |
214 | apic_driver(xen_pv_apic); | ||
diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c index 81665c9f2132..94578efd3067 100644 --- a/arch/x86/xen/enlighten.c +++ b/arch/x86/xen/enlighten.c | |||
@@ -928,92 +928,6 @@ static void xen_io_delay(void) | |||
928 | { | 928 | { |
929 | } | 929 | } |
930 | 930 | ||
931 | #ifdef CONFIG_X86_LOCAL_APIC | ||
932 | static unsigned long xen_set_apic_id(unsigned int x) | ||
933 | { | ||
934 | WARN_ON(1); | ||
935 | return x; | ||
936 | } | ||
937 | static unsigned int xen_get_apic_id(unsigned long x) | ||
938 | { | ||
939 | return ((x)>>24) & 0xFFu; | ||
940 | } | ||
941 | static u32 xen_apic_read(u32 reg) | ||
942 | { | ||
943 | struct xen_platform_op op = { | ||
944 | .cmd = XENPF_get_cpuinfo, | ||
945 | .interface_version = XENPF_INTERFACE_VERSION, | ||
946 | .u.pcpu_info.xen_cpuid = 0, | ||
947 | }; | ||
948 | int ret = 0; | ||
949 | |||
950 | /* Shouldn't need this as APIC is turned off for PV, and we only | ||
951 | * get called on the bootup processor. But just in case. */ | ||
952 | if (!xen_initial_domain() || smp_processor_id()) | ||
953 | return 0; | ||
954 | |||
955 | if (reg == APIC_LVR) | ||
956 | return 0x10; | ||
957 | |||
958 | if (reg != APIC_ID) | ||
959 | return 0; | ||
960 | |||
961 | ret = HYPERVISOR_dom0_op(&op); | ||
962 | if (ret) | ||
963 | return 0; | ||
964 | |||
965 | return op.u.pcpu_info.apic_id << 24; | ||
966 | } | ||
967 | |||
968 | static void xen_apic_write(u32 reg, u32 val) | ||
969 | { | ||
970 | /* Warn to see if there's any stray references */ | ||
971 | WARN_ON(1); | ||
972 | } | ||
973 | |||
974 | static u64 xen_apic_icr_read(void) | ||
975 | { | ||
976 | return 0; | ||
977 | } | ||
978 | |||
979 | static void xen_apic_icr_write(u32 low, u32 id) | ||
980 | { | ||
981 | /* Warn to see if there's any stray references */ | ||
982 | WARN_ON(1); | ||
983 | } | ||
984 | |||
985 | static void xen_apic_wait_icr_idle(void) | ||
986 | { | ||
987 | return; | ||
988 | } | ||
989 | |||
990 | static u32 xen_safe_apic_wait_icr_idle(void) | ||
991 | { | ||
992 | return 0; | ||
993 | } | ||
994 | |||
995 | static void set_xen_basic_apic_ops(void) | ||
996 | { | ||
997 | apic->read = xen_apic_read; | ||
998 | apic->write = xen_apic_write; | ||
999 | apic->icr_read = xen_apic_icr_read; | ||
1000 | apic->icr_write = xen_apic_icr_write; | ||
1001 | apic->wait_icr_idle = xen_apic_wait_icr_idle; | ||
1002 | apic->safe_wait_icr_idle = xen_safe_apic_wait_icr_idle; | ||
1003 | apic->set_apic_id = xen_set_apic_id; | ||
1004 | apic->get_apic_id = xen_get_apic_id; | ||
1005 | |||
1006 | #ifdef CONFIG_SMP | ||
1007 | apic->send_IPI_allbutself = xen_send_IPI_allbutself; | ||
1008 | apic->send_IPI_mask_allbutself = xen_send_IPI_mask_allbutself; | ||
1009 | apic->send_IPI_mask = xen_send_IPI_mask; | ||
1010 | apic->send_IPI_all = xen_send_IPI_all; | ||
1011 | apic->send_IPI_self = xen_send_IPI_self; | ||
1012 | #endif | ||
1013 | } | ||
1014 | |||
1015 | #endif | ||
1016 | |||
1017 | static void xen_clts(void) | 931 | static void xen_clts(void) |
1018 | { | 932 | { |
1019 | struct multicall_space mcs; | 933 | struct multicall_space mcs; |
@@ -1619,7 +1533,7 @@ asmlinkage __visible void __init xen_start_kernel(void) | |||
1619 | /* | 1533 | /* |
1620 | * set up the basic apic ops. | 1534 | * set up the basic apic ops. |
1621 | */ | 1535 | */ |
1622 | set_xen_basic_apic_ops(); | 1536 | xen_init_apic(); |
1623 | #endif | 1537 | #endif |
1624 | 1538 | ||
1625 | if (xen_feature(XENFEAT_mmu_pt_update_preserve_ad)) { | 1539 | if (xen_feature(XENFEAT_mmu_pt_update_preserve_ad)) { |
@@ -1732,8 +1646,6 @@ asmlinkage __visible void __init xen_start_kernel(void) | |||
1732 | if (HYPERVISOR_dom0_op(&op) == 0) | 1646 | if (HYPERVISOR_dom0_op(&op) == 0) |
1733 | boot_params.kbd_status = op.u.firmware_info.u.kbd_shift_flags; | 1647 | boot_params.kbd_status = op.u.firmware_info.u.kbd_shift_flags; |
1734 | 1648 | ||
1735 | xen_init_apic(); | ||
1736 | |||
1737 | /* Make sure ACS will be enabled */ | 1649 | /* Make sure ACS will be enabled */ |
1738 | pci_request_acs(); | 1650 | pci_request_acs(); |
1739 | 1651 | ||
diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c index 65083ad63b6f..dd151b2045b0 100644 --- a/arch/x86/xen/mmu.c +++ b/arch/x86/xen/mmu.c | |||
@@ -2436,99 +2436,11 @@ void __init xen_hvm_init_mmu_ops(void) | |||
2436 | } | 2436 | } |
2437 | #endif | 2437 | #endif |
2438 | 2438 | ||
2439 | #ifdef CONFIG_XEN_PVH | ||
2440 | /* | ||
2441 | * Map foreign gfn (fgfn), to local pfn (lpfn). This for the user | ||
2442 | * space creating new guest on pvh dom0 and needing to map domU pages. | ||
2443 | */ | ||
2444 | static int xlate_add_to_p2m(unsigned long lpfn, unsigned long fgfn, | ||
2445 | unsigned int domid) | ||
2446 | { | ||
2447 | int rc, err = 0; | ||
2448 | xen_pfn_t gpfn = lpfn; | ||
2449 | xen_ulong_t idx = fgfn; | ||
2450 | |||
2451 | struct xen_add_to_physmap_range xatp = { | ||
2452 | .domid = DOMID_SELF, | ||
2453 | .foreign_domid = domid, | ||
2454 | .size = 1, | ||
2455 | .space = XENMAPSPACE_gmfn_foreign, | ||
2456 | }; | ||
2457 | set_xen_guest_handle(xatp.idxs, &idx); | ||
2458 | set_xen_guest_handle(xatp.gpfns, &gpfn); | ||
2459 | set_xen_guest_handle(xatp.errs, &err); | ||
2460 | |||
2461 | rc = HYPERVISOR_memory_op(XENMEM_add_to_physmap_range, &xatp); | ||
2462 | if (rc < 0) | ||
2463 | return rc; | ||
2464 | return err; | ||
2465 | } | ||
2466 | |||
2467 | static int xlate_remove_from_p2m(unsigned long spfn, int count) | ||
2468 | { | ||
2469 | struct xen_remove_from_physmap xrp; | ||
2470 | int i, rc; | ||
2471 | |||
2472 | for (i = 0; i < count; i++) { | ||
2473 | xrp.domid = DOMID_SELF; | ||
2474 | xrp.gpfn = spfn+i; | ||
2475 | rc = HYPERVISOR_memory_op(XENMEM_remove_from_physmap, &xrp); | ||
2476 | if (rc) | ||
2477 | break; | ||
2478 | } | ||
2479 | return rc; | ||
2480 | } | ||
2481 | |||
2482 | struct xlate_remap_data { | ||
2483 | unsigned long fgfn; /* foreign domain's gfn */ | ||
2484 | pgprot_t prot; | ||
2485 | domid_t domid; | ||
2486 | int index; | ||
2487 | struct page **pages; | ||
2488 | }; | ||
2489 | |||
2490 | static int xlate_map_pte_fn(pte_t *ptep, pgtable_t token, unsigned long addr, | ||
2491 | void *data) | ||
2492 | { | ||
2493 | int rc; | ||
2494 | struct xlate_remap_data *remap = data; | ||
2495 | unsigned long pfn = page_to_pfn(remap->pages[remap->index++]); | ||
2496 | pte_t pteval = pte_mkspecial(pfn_pte(pfn, remap->prot)); | ||
2497 | |||
2498 | rc = xlate_add_to_p2m(pfn, remap->fgfn, remap->domid); | ||
2499 | if (rc) | ||
2500 | return rc; | ||
2501 | native_set_pte(ptep, pteval); | ||
2502 | |||
2503 | return 0; | ||
2504 | } | ||
2505 | |||
2506 | static int xlate_remap_gfn_range(struct vm_area_struct *vma, | ||
2507 | unsigned long addr, unsigned long mfn, | ||
2508 | int nr, pgprot_t prot, unsigned domid, | ||
2509 | struct page **pages) | ||
2510 | { | ||
2511 | int err; | ||
2512 | struct xlate_remap_data pvhdata; | ||
2513 | |||
2514 | BUG_ON(!pages); | ||
2515 | |||
2516 | pvhdata.fgfn = mfn; | ||
2517 | pvhdata.prot = prot; | ||
2518 | pvhdata.domid = domid; | ||
2519 | pvhdata.index = 0; | ||
2520 | pvhdata.pages = pages; | ||
2521 | err = apply_to_page_range(vma->vm_mm, addr, nr << PAGE_SHIFT, | ||
2522 | xlate_map_pte_fn, &pvhdata); | ||
2523 | flush_tlb_all(); | ||
2524 | return err; | ||
2525 | } | ||
2526 | #endif | ||
2527 | |||
2528 | #define REMAP_BATCH_SIZE 16 | 2439 | #define REMAP_BATCH_SIZE 16 |
2529 | 2440 | ||
2530 | struct remap_data { | 2441 | struct remap_data { |
2531 | unsigned long mfn; | 2442 | xen_pfn_t *mfn; |
2443 | bool contiguous; | ||
2532 | pgprot_t prot; | 2444 | pgprot_t prot; |
2533 | struct mmu_update *mmu_update; | 2445 | struct mmu_update *mmu_update; |
2534 | }; | 2446 | }; |
@@ -2537,7 +2449,14 @@ static int remap_area_mfn_pte_fn(pte_t *ptep, pgtable_t token, | |||
2537 | unsigned long addr, void *data) | 2449 | unsigned long addr, void *data) |
2538 | { | 2450 | { |
2539 | struct remap_data *rmd = data; | 2451 | struct remap_data *rmd = data; |
2540 | pte_t pte = pte_mkspecial(mfn_pte(rmd->mfn++, rmd->prot)); | 2452 | pte_t pte = pte_mkspecial(mfn_pte(*rmd->mfn, rmd->prot)); |
2453 | |||
2454 | /* If we have a contigious range, just update the mfn itself, | ||
2455 | else update pointer to be "next mfn". */ | ||
2456 | if (rmd->contiguous) | ||
2457 | (*rmd->mfn)++; | ||
2458 | else | ||
2459 | rmd->mfn++; | ||
2541 | 2460 | ||
2542 | rmd->mmu_update->ptr = virt_to_machine(ptep).maddr; | 2461 | rmd->mmu_update->ptr = virt_to_machine(ptep).maddr; |
2543 | rmd->mmu_update->val = pte_val_ma(pte); | 2462 | rmd->mmu_update->val = pte_val_ma(pte); |
@@ -2546,26 +2465,26 @@ static int remap_area_mfn_pte_fn(pte_t *ptep, pgtable_t token, | |||
2546 | return 0; | 2465 | return 0; |
2547 | } | 2466 | } |
2548 | 2467 | ||
2549 | int xen_remap_domain_mfn_range(struct vm_area_struct *vma, | 2468 | static int do_remap_mfn(struct vm_area_struct *vma, |
2550 | unsigned long addr, | 2469 | unsigned long addr, |
2551 | xen_pfn_t mfn, int nr, | 2470 | xen_pfn_t *mfn, int nr, |
2552 | pgprot_t prot, unsigned domid, | 2471 | int *err_ptr, pgprot_t prot, |
2553 | struct page **pages) | 2472 | unsigned domid, |
2554 | 2473 | struct page **pages) | |
2555 | { | 2474 | { |
2475 | int err = 0; | ||
2556 | struct remap_data rmd; | 2476 | struct remap_data rmd; |
2557 | struct mmu_update mmu_update[REMAP_BATCH_SIZE]; | 2477 | struct mmu_update mmu_update[REMAP_BATCH_SIZE]; |
2558 | int batch; | ||
2559 | unsigned long range; | 2478 | unsigned long range; |
2560 | int err = 0; | 2479 | int mapped = 0; |
2561 | 2480 | ||
2562 | BUG_ON(!((vma->vm_flags & (VM_PFNMAP | VM_IO)) == (VM_PFNMAP | VM_IO))); | 2481 | BUG_ON(!((vma->vm_flags & (VM_PFNMAP | VM_IO)) == (VM_PFNMAP | VM_IO))); |
2563 | 2482 | ||
2564 | if (xen_feature(XENFEAT_auto_translated_physmap)) { | 2483 | if (xen_feature(XENFEAT_auto_translated_physmap)) { |
2565 | #ifdef CONFIG_XEN_PVH | 2484 | #ifdef CONFIG_XEN_PVH |
2566 | /* We need to update the local page tables and the xen HAP */ | 2485 | /* We need to update the local page tables and the xen HAP */ |
2567 | return xlate_remap_gfn_range(vma, addr, mfn, nr, prot, | 2486 | return xen_xlate_remap_gfn_array(vma, addr, mfn, nr, err_ptr, |
2568 | domid, pages); | 2487 | prot, domid, pages); |
2569 | #else | 2488 | #else |
2570 | return -EINVAL; | 2489 | return -EINVAL; |
2571 | #endif | 2490 | #endif |
@@ -2573,9 +2492,15 @@ int xen_remap_domain_mfn_range(struct vm_area_struct *vma, | |||
2573 | 2492 | ||
2574 | rmd.mfn = mfn; | 2493 | rmd.mfn = mfn; |
2575 | rmd.prot = prot; | 2494 | rmd.prot = prot; |
2495 | /* We use the err_ptr to indicate if there we are doing a contigious | ||
2496 | * mapping or a discontigious mapping. */ | ||
2497 | rmd.contiguous = !err_ptr; | ||
2576 | 2498 | ||
2577 | while (nr) { | 2499 | while (nr) { |
2578 | batch = min(REMAP_BATCH_SIZE, nr); | 2500 | int index = 0; |
2501 | int done = 0; | ||
2502 | int batch = min(REMAP_BATCH_SIZE, nr); | ||
2503 | int batch_left = batch; | ||
2579 | range = (unsigned long)batch << PAGE_SHIFT; | 2504 | range = (unsigned long)batch << PAGE_SHIFT; |
2580 | 2505 | ||
2581 | rmd.mmu_update = mmu_update; | 2506 | rmd.mmu_update = mmu_update; |
@@ -2584,23 +2509,72 @@ int xen_remap_domain_mfn_range(struct vm_area_struct *vma, | |||
2584 | if (err) | 2509 | if (err) |
2585 | goto out; | 2510 | goto out; |
2586 | 2511 | ||
2587 | err = HYPERVISOR_mmu_update(mmu_update, batch, NULL, domid); | 2512 | /* We record the error for each page that gives an error, but |
2588 | if (err < 0) | 2513 | * continue mapping until the whole set is done */ |
2589 | goto out; | 2514 | do { |
2515 | int i; | ||
2516 | |||
2517 | err = HYPERVISOR_mmu_update(&mmu_update[index], | ||
2518 | batch_left, &done, domid); | ||
2519 | |||
2520 | /* | ||
2521 | * @err_ptr may be the same buffer as @mfn, so | ||
2522 | * only clear it after each chunk of @mfn is | ||
2523 | * used. | ||
2524 | */ | ||
2525 | if (err_ptr) { | ||
2526 | for (i = index; i < index + done; i++) | ||
2527 | err_ptr[i] = 0; | ||
2528 | } | ||
2529 | if (err < 0) { | ||
2530 | if (!err_ptr) | ||
2531 | goto out; | ||
2532 | err_ptr[i] = err; | ||
2533 | done++; /* Skip failed frame. */ | ||
2534 | } else | ||
2535 | mapped += done; | ||
2536 | batch_left -= done; | ||
2537 | index += done; | ||
2538 | } while (batch_left); | ||
2590 | 2539 | ||
2591 | nr -= batch; | 2540 | nr -= batch; |
2592 | addr += range; | 2541 | addr += range; |
2542 | if (err_ptr) | ||
2543 | err_ptr += batch; | ||
2593 | } | 2544 | } |
2594 | |||
2595 | err = 0; | ||
2596 | out: | 2545 | out: |
2597 | 2546 | ||
2598 | xen_flush_tlb_all(); | 2547 | xen_flush_tlb_all(); |
2599 | 2548 | ||
2600 | return err; | 2549 | return err < 0 ? err : mapped; |
2550 | } | ||
2551 | |||
2552 | int xen_remap_domain_mfn_range(struct vm_area_struct *vma, | ||
2553 | unsigned long addr, | ||
2554 | xen_pfn_t mfn, int nr, | ||
2555 | pgprot_t prot, unsigned domid, | ||
2556 | struct page **pages) | ||
2557 | { | ||
2558 | return do_remap_mfn(vma, addr, &mfn, nr, NULL, prot, domid, pages); | ||
2601 | } | 2559 | } |
2602 | EXPORT_SYMBOL_GPL(xen_remap_domain_mfn_range); | 2560 | EXPORT_SYMBOL_GPL(xen_remap_domain_mfn_range); |
2603 | 2561 | ||
2562 | int xen_remap_domain_mfn_array(struct vm_area_struct *vma, | ||
2563 | unsigned long addr, | ||
2564 | xen_pfn_t *mfn, int nr, | ||
2565 | int *err_ptr, pgprot_t prot, | ||
2566 | unsigned domid, struct page **pages) | ||
2567 | { | ||
2568 | /* We BUG_ON because it's a programmer error to pass a NULL err_ptr, | ||
2569 | * and the consequences later is quite hard to detect what the actual | ||
2570 | * cause of "wrong memory was mapped in". | ||
2571 | */ | ||
2572 | BUG_ON(err_ptr == NULL); | ||
2573 | return do_remap_mfn(vma, addr, mfn, nr, err_ptr, prot, domid, pages); | ||
2574 | } | ||
2575 | EXPORT_SYMBOL_GPL(xen_remap_domain_mfn_array); | ||
2576 | |||
2577 | |||
2604 | /* Returns: 0 success */ | 2578 | /* Returns: 0 success */ |
2605 | int xen_unmap_domain_mfn_range(struct vm_area_struct *vma, | 2579 | int xen_unmap_domain_mfn_range(struct vm_area_struct *vma, |
2606 | int numpgs, struct page **pages) | 2580 | int numpgs, struct page **pages) |
@@ -2609,22 +2583,7 @@ int xen_unmap_domain_mfn_range(struct vm_area_struct *vma, | |||
2609 | return 0; | 2583 | return 0; |
2610 | 2584 | ||
2611 | #ifdef CONFIG_XEN_PVH | 2585 | #ifdef CONFIG_XEN_PVH |
2612 | while (numpgs--) { | 2586 | return xen_xlate_unmap_gfn_range(vma, numpgs, pages); |
2613 | /* | ||
2614 | * The mmu has already cleaned up the process mmu | ||
2615 | * resources at this point (lookup_address will return | ||
2616 | * NULL). | ||
2617 | */ | ||
2618 | unsigned long pfn = page_to_pfn(pages[numpgs]); | ||
2619 | |||
2620 | xlate_remove_from_p2m(pfn, 1); | ||
2621 | } | ||
2622 | /* | ||
2623 | * We don't need to flush tlbs because as part of | ||
2624 | * xlate_remove_from_p2m, the hypervisor will do tlb flushes | ||
2625 | * after removing the p2m entries from the EPT/NPT | ||
2626 | */ | ||
2627 | return 0; | ||
2628 | #else | 2587 | #else |
2629 | return -EINVAL; | 2588 | return -EINVAL; |
2630 | #endif | 2589 | #endif |
diff --git a/arch/x86/xen/trace.c b/arch/x86/xen/trace.c index 520022d1a181..a702ec2f5931 100644 --- a/arch/x86/xen/trace.c +++ b/arch/x86/xen/trace.c | |||
@@ -1,54 +1,12 @@ | |||
1 | #include <linux/ftrace.h> | 1 | #include <linux/ftrace.h> |
2 | #include <xen/interface/xen.h> | 2 | #include <xen/interface/xen.h> |
3 | #include <xen/interface/xen-mca.h> | ||
3 | 4 | ||
4 | #define N(x) [__HYPERVISOR_##x] = "("#x")" | 5 | #define HYPERCALL(x) [__HYPERVISOR_##x] = "("#x")", |
5 | static const char *xen_hypercall_names[] = { | 6 | static const char *xen_hypercall_names[] = { |
6 | N(set_trap_table), | 7 | #include <asm/xen-hypercalls.h> |
7 | N(mmu_update), | ||
8 | N(set_gdt), | ||
9 | N(stack_switch), | ||
10 | N(set_callbacks), | ||
11 | N(fpu_taskswitch), | ||
12 | N(sched_op_compat), | ||
13 | N(dom0_op), | ||
14 | N(set_debugreg), | ||
15 | N(get_debugreg), | ||
16 | N(update_descriptor), | ||
17 | N(memory_op), | ||
18 | N(multicall), | ||
19 | N(update_va_mapping), | ||
20 | N(set_timer_op), | ||
21 | N(event_channel_op_compat), | ||
22 | N(xen_version), | ||
23 | N(console_io), | ||
24 | N(physdev_op_compat), | ||
25 | N(grant_table_op), | ||
26 | N(vm_assist), | ||
27 | N(update_va_mapping_otherdomain), | ||
28 | N(iret), | ||
29 | N(vcpu_op), | ||
30 | N(set_segment_base), | ||
31 | N(mmuext_op), | ||
32 | N(acm_op), | ||
33 | N(nmi_op), | ||
34 | N(sched_op), | ||
35 | N(callback_op), | ||
36 | N(xenoprof_op), | ||
37 | N(event_channel_op), | ||
38 | N(physdev_op), | ||
39 | N(hvm_op), | ||
40 | |||
41 | /* Architecture-specific hypercall definitions. */ | ||
42 | N(arch_0), | ||
43 | N(arch_1), | ||
44 | N(arch_2), | ||
45 | N(arch_3), | ||
46 | N(arch_4), | ||
47 | N(arch_5), | ||
48 | N(arch_6), | ||
49 | N(arch_7), | ||
50 | }; | 8 | }; |
51 | #undef N | 9 | #undef HYPERCALL |
52 | 10 | ||
53 | static const char *xen_hypercall_name(unsigned op) | 11 | static const char *xen_hypercall_name(unsigned op) |
54 | { | 12 | { |
diff --git a/arch/x86/xen/xen-head.S b/arch/x86/xen/xen-head.S index 674b222544b7..8afdfccf6086 100644 --- a/arch/x86/xen/xen-head.S +++ b/arch/x86/xen/xen-head.S | |||
@@ -12,6 +12,8 @@ | |||
12 | 12 | ||
13 | #include <xen/interface/elfnote.h> | 13 | #include <xen/interface/elfnote.h> |
14 | #include <xen/interface/features.h> | 14 | #include <xen/interface/features.h> |
15 | #include <xen/interface/xen.h> | ||
16 | #include <xen/interface/xen-mca.h> | ||
15 | #include <asm/xen/interface.h> | 17 | #include <asm/xen/interface.h> |
16 | 18 | ||
17 | #ifdef CONFIG_XEN_PVH | 19 | #ifdef CONFIG_XEN_PVH |
@@ -85,59 +87,14 @@ ENTRY(xen_pvh_early_cpu_init) | |||
85 | .pushsection .text | 87 | .pushsection .text |
86 | .balign PAGE_SIZE | 88 | .balign PAGE_SIZE |
87 | ENTRY(hypercall_page) | 89 | ENTRY(hypercall_page) |
88 | #define NEXT_HYPERCALL(x) \ | 90 | .skip PAGE_SIZE |
89 | ENTRY(xen_hypercall_##x) \ | 91 | |
90 | .skip 32 | 92 | #define HYPERCALL(n) \ |
91 | 93 | .equ xen_hypercall_##n, hypercall_page + __HYPERVISOR_##n * 32; \ | |
92 | NEXT_HYPERCALL(set_trap_table) | 94 | .type xen_hypercall_##n, @function; .size xen_hypercall_##n, 32 |
93 | NEXT_HYPERCALL(mmu_update) | 95 | #include <asm/xen-hypercalls.h> |
94 | NEXT_HYPERCALL(set_gdt) | 96 | #undef HYPERCALL |
95 | NEXT_HYPERCALL(stack_switch) | 97 | |
96 | NEXT_HYPERCALL(set_callbacks) | ||
97 | NEXT_HYPERCALL(fpu_taskswitch) | ||
98 | NEXT_HYPERCALL(sched_op_compat) | ||
99 | NEXT_HYPERCALL(platform_op) | ||
100 | NEXT_HYPERCALL(set_debugreg) | ||
101 | NEXT_HYPERCALL(get_debugreg) | ||
102 | NEXT_HYPERCALL(update_descriptor) | ||
103 | NEXT_HYPERCALL(ni) | ||
104 | NEXT_HYPERCALL(memory_op) | ||
105 | NEXT_HYPERCALL(multicall) | ||
106 | NEXT_HYPERCALL(update_va_mapping) | ||
107 | NEXT_HYPERCALL(set_timer_op) | ||
108 | NEXT_HYPERCALL(event_channel_op_compat) | ||
109 | NEXT_HYPERCALL(xen_version) | ||
110 | NEXT_HYPERCALL(console_io) | ||
111 | NEXT_HYPERCALL(physdev_op_compat) | ||
112 | NEXT_HYPERCALL(grant_table_op) | ||
113 | NEXT_HYPERCALL(vm_assist) | ||
114 | NEXT_HYPERCALL(update_va_mapping_otherdomain) | ||
115 | NEXT_HYPERCALL(iret) | ||
116 | NEXT_HYPERCALL(vcpu_op) | ||
117 | NEXT_HYPERCALL(set_segment_base) | ||
118 | NEXT_HYPERCALL(mmuext_op) | ||
119 | NEXT_HYPERCALL(xsm_op) | ||
120 | NEXT_HYPERCALL(nmi_op) | ||
121 | NEXT_HYPERCALL(sched_op) | ||
122 | NEXT_HYPERCALL(callback_op) | ||
123 | NEXT_HYPERCALL(xenoprof_op) | ||
124 | NEXT_HYPERCALL(event_channel_op) | ||
125 | NEXT_HYPERCALL(physdev_op) | ||
126 | NEXT_HYPERCALL(hvm_op) | ||
127 | NEXT_HYPERCALL(sysctl) | ||
128 | NEXT_HYPERCALL(domctl) | ||
129 | NEXT_HYPERCALL(kexec_op) | ||
130 | NEXT_HYPERCALL(tmem_op) /* 38 */ | ||
131 | ENTRY(xen_hypercall_rsvr) | ||
132 | .skip 320 | ||
133 | NEXT_HYPERCALL(mca) /* 48 */ | ||
134 | NEXT_HYPERCALL(arch_1) | ||
135 | NEXT_HYPERCALL(arch_2) | ||
136 | NEXT_HYPERCALL(arch_3) | ||
137 | NEXT_HYPERCALL(arch_4) | ||
138 | NEXT_HYPERCALL(arch_5) | ||
139 | NEXT_HYPERCALL(arch_6) | ||
140 | .balign PAGE_SIZE | ||
141 | .popsection | 98 | .popsection |
142 | 99 | ||
143 | ELFNOTE(Xen, XEN_ELFNOTE_GUEST_OS, .asciz "linux") | 100 | ELFNOTE(Xen, XEN_ELFNOTE_GUEST_OS, .asciz "linux") |