diff options
Diffstat (limited to 'arch/x86')
| -rw-r--r-- | arch/x86/syscalls/Makefile | 9 | ||||
| -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 |
6 files changed, 287 insertions, 312 deletions
diff --git a/arch/x86/syscalls/Makefile b/arch/x86/syscalls/Makefile index 3323c2745248..a55abb9f6c5e 100644 --- a/arch/x86/syscalls/Makefile +++ b/arch/x86/syscalls/Makefile | |||
| @@ -19,6 +19,9 @@ quiet_cmd_syshdr = SYSHDR $@ | |||
| 19 | quiet_cmd_systbl = SYSTBL $@ | 19 | quiet_cmd_systbl = SYSTBL $@ |
| 20 | cmd_systbl = $(CONFIG_SHELL) '$(systbl)' $< $@ | 20 | cmd_systbl = $(CONFIG_SHELL) '$(systbl)' $< $@ |
| 21 | 21 | ||
| 22 | quiet_cmd_hypercalls = HYPERCALLS $@ | ||
| 23 | cmd_hypercalls = $(CONFIG_SHELL) '$<' $@ $(filter-out $<,$^) | ||
| 24 | |||
| 22 | syshdr_abi_unistd_32 := i386 | 25 | syshdr_abi_unistd_32 := i386 |
| 23 | $(uapi)/unistd_32.h: $(syscall32) $(syshdr) | 26 | $(uapi)/unistd_32.h: $(syscall32) $(syshdr) |
| 24 | $(call if_changed,syshdr) | 27 | $(call if_changed,syshdr) |
| @@ -47,10 +50,16 @@ $(out)/syscalls_32.h: $(syscall32) $(systbl) | |||
| 47 | $(out)/syscalls_64.h: $(syscall64) $(systbl) | 50 | $(out)/syscalls_64.h: $(syscall64) $(systbl) |
| 48 | $(call if_changed,systbl) | 51 | $(call if_changed,systbl) |
| 49 | 52 | ||
| 53 | $(out)/xen-hypercalls.h: $(srctree)/scripts/xen-hypercalls.sh | ||
| 54 | $(call if_changed,hypercalls) | ||
| 55 | |||
| 56 | $(out)/xen-hypercalls.h: $(srctree)/include/xen/interface/xen*.h | ||
| 57 | |||
| 50 | uapisyshdr-y += unistd_32.h unistd_64.h unistd_x32.h | 58 | uapisyshdr-y += unistd_32.h unistd_64.h unistd_x32.h |
| 51 | syshdr-y += syscalls_32.h | 59 | syshdr-y += syscalls_32.h |
| 52 | syshdr-$(CONFIG_X86_64) += unistd_32_ia32.h unistd_64_x32.h | 60 | syshdr-$(CONFIG_X86_64) += unistd_32_ia32.h unistd_64_x32.h |
| 53 | syshdr-$(CONFIG_X86_64) += syscalls_64.h | 61 | syshdr-$(CONFIG_X86_64) += syscalls_64.h |
| 62 | syshdr-$(CONFIG_XEN) += xen-hypercalls.h | ||
| 54 | 63 | ||
| 55 | targets += $(uapisyshdr-y) $(syshdr-y) | 64 | targets += $(uapisyshdr-y) $(syshdr-y) |
| 56 | 65 | ||
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") |
