diff options
author | Jeremy Fitzhardinge <jeremy@xensource.com> | 2007-10-16 14:51:29 -0400 |
---|---|---|
committer | Jeremy Fitzhardinge <jeremy@goop.org> | 2007-10-16 14:51:29 -0400 |
commit | 93b1eab3d29e7ea32ee583de3362da84db06ded8 (patch) | |
tree | 8dc7eb61d4c65a48f9ce21a49e392f4967185cfd /arch/x86/xen/enlighten.c | |
parent | ab9c232286c2b77be78441c2d8396500b045777e (diff) |
paravirt: refactor struct paravirt_ops into smaller pv_*_ops
This patch refactors the paravirt_ops structure into groups of
functionally related ops:
pv_info - random info, rather than function entrypoints
pv_init_ops - functions used at boot time (some for module_init too)
pv_misc_ops - lazy mode, which didn't fit well anywhere else
pv_time_ops - time-related functions
pv_cpu_ops - various privileged instruction ops
pv_irq_ops - operations for managing interrupt state
pv_apic_ops - APIC operations
pv_mmu_ops - operations for managing pagetables
There are several motivations for this:
1. Some of these ops will be general to all x86, and some will be
i386/x86-64 specific. This makes it easier to share common stuff
while allowing separate implementations where needed.
2. At the moment we must export all of paravirt_ops, but modules only
need selected parts of it. This allows us to export on a case by case
basis (and also choose which export license we want to apply).
3. Functional groupings make things a bit more readable.
Struct paravirt_ops is now only used as a template to generate
patch-site identifiers, and to extract function pointers for inserting
into jmp/calls when patching. It is only instantiated when needed.
Signed-off-by: Jeremy Fitzhardinge <jeremy@xensource.com>
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Cc: Andi Kleen <ak@suse.de>
Cc: Zach Amsden <zach@vmware.com>
Cc: Avi Kivity <avi@qumranet.com>
Cc: Anthony Liguory <aliguori@us.ibm.com>
Cc: "Glauber de Oliveira Costa" <glommer@gmail.com>
Cc: Jun Nakajima <jun.nakajima@intel.com>
Diffstat (limited to 'arch/x86/xen/enlighten.c')
-rw-r--r-- | arch/x86/xen/enlighten.c | 98 |
1 files changed, 61 insertions, 37 deletions
diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c index f01bfcd4bdee..3d3bf05dec7f 100644 --- a/arch/x86/xen/enlighten.c +++ b/arch/x86/xen/enlighten.c | |||
@@ -124,7 +124,7 @@ static void __init xen_vcpu_setup(int cpu) | |||
124 | static void __init xen_banner(void) | 124 | static void __init xen_banner(void) |
125 | { | 125 | { |
126 | printk(KERN_INFO "Booting paravirtualized kernel on %s\n", | 126 | printk(KERN_INFO "Booting paravirtualized kernel on %s\n", |
127 | paravirt_ops.name); | 127 | pv_info.name); |
128 | printk(KERN_INFO "Hypervisor signature: %s\n", xen_start_info->magic); | 128 | printk(KERN_INFO "Hypervisor signature: %s\n", xen_start_info->magic); |
129 | } | 129 | } |
130 | 130 | ||
@@ -738,7 +738,7 @@ static __init void xen_pagetable_setup_start(pgd_t *base) | |||
738 | pgd_t *xen_pgd = (pgd_t *)xen_start_info->pt_base; | 738 | pgd_t *xen_pgd = (pgd_t *)xen_start_info->pt_base; |
739 | 739 | ||
740 | /* special set_pte for pagetable initialization */ | 740 | /* special set_pte for pagetable initialization */ |
741 | paravirt_ops.set_pte = xen_set_pte_init; | 741 | pv_mmu_ops.set_pte = xen_set_pte_init; |
742 | 742 | ||
743 | init_mm.pgd = base; | 743 | init_mm.pgd = base; |
744 | /* | 744 | /* |
@@ -785,8 +785,8 @@ static __init void xen_pagetable_setup_done(pgd_t *base) | |||
785 | { | 785 | { |
786 | /* This will work as long as patching hasn't happened yet | 786 | /* This will work as long as patching hasn't happened yet |
787 | (which it hasn't) */ | 787 | (which it hasn't) */ |
788 | paravirt_ops.alloc_pt = xen_alloc_pt; | 788 | pv_mmu_ops.alloc_pt = xen_alloc_pt; |
789 | paravirt_ops.set_pte = xen_set_pte; | 789 | pv_mmu_ops.set_pte = xen_set_pte; |
790 | 790 | ||
791 | if (!xen_feature(XENFEAT_auto_translated_physmap)) { | 791 | if (!xen_feature(XENFEAT_auto_translated_physmap)) { |
792 | /* | 792 | /* |
@@ -833,12 +833,12 @@ void __init xen_setup_vcpu_info_placement(void) | |||
833 | if (have_vcpu_info_placement) { | 833 | if (have_vcpu_info_placement) { |
834 | printk(KERN_INFO "Xen: using vcpu_info placement\n"); | 834 | printk(KERN_INFO "Xen: using vcpu_info placement\n"); |
835 | 835 | ||
836 | paravirt_ops.save_fl = xen_save_fl_direct; | 836 | pv_irq_ops.save_fl = xen_save_fl_direct; |
837 | paravirt_ops.restore_fl = xen_restore_fl_direct; | 837 | pv_irq_ops.restore_fl = xen_restore_fl_direct; |
838 | paravirt_ops.irq_disable = xen_irq_disable_direct; | 838 | pv_irq_ops.irq_disable = xen_irq_disable_direct; |
839 | paravirt_ops.irq_enable = xen_irq_enable_direct; | 839 | pv_irq_ops.irq_enable = xen_irq_enable_direct; |
840 | paravirt_ops.read_cr2 = xen_read_cr2_direct; | 840 | pv_mmu_ops.read_cr2 = xen_read_cr2_direct; |
841 | paravirt_ops.iret = xen_iret_direct; | 841 | pv_cpu_ops.iret = xen_iret_direct; |
842 | } | 842 | } |
843 | } | 843 | } |
844 | 844 | ||
@@ -850,8 +850,8 @@ static unsigned xen_patch(u8 type, u16 clobbers, void *insnbuf, | |||
850 | 850 | ||
851 | start = end = reloc = NULL; | 851 | start = end = reloc = NULL; |
852 | 852 | ||
853 | #define SITE(x) \ | 853 | #define SITE(op, x) \ |
854 | case PARAVIRT_PATCH(x): \ | 854 | case PARAVIRT_PATCH(op.x): \ |
855 | if (have_vcpu_info_placement) { \ | 855 | if (have_vcpu_info_placement) { \ |
856 | start = (char *)xen_##x##_direct; \ | 856 | start = (char *)xen_##x##_direct; \ |
857 | end = xen_##x##_direct_end; \ | 857 | end = xen_##x##_direct_end; \ |
@@ -860,10 +860,10 @@ static unsigned xen_patch(u8 type, u16 clobbers, void *insnbuf, | |||
860 | goto patch_site | 860 | goto patch_site |
861 | 861 | ||
862 | switch (type) { | 862 | switch (type) { |
863 | SITE(irq_enable); | 863 | SITE(pv_irq_ops, irq_enable); |
864 | SITE(irq_disable); | 864 | SITE(pv_irq_ops, irq_disable); |
865 | SITE(save_fl); | 865 | SITE(pv_irq_ops, save_fl); |
866 | SITE(restore_fl); | 866 | SITE(pv_irq_ops, restore_fl); |
867 | #undef SITE | 867 | #undef SITE |
868 | 868 | ||
869 | patch_site: | 869 | patch_site: |
@@ -895,26 +895,32 @@ static unsigned xen_patch(u8 type, u16 clobbers, void *insnbuf, | |||
895 | return ret; | 895 | return ret; |
896 | } | 896 | } |
897 | 897 | ||
898 | static const struct paravirt_ops xen_paravirt_ops __initdata = { | 898 | static const struct pv_info xen_info __initdata = { |
899 | .paravirt_enabled = 1, | 899 | .paravirt_enabled = 1, |
900 | .shared_kernel_pmd = 0, | 900 | .shared_kernel_pmd = 0, |
901 | 901 | ||
902 | .name = "Xen", | 902 | .name = "Xen", |
903 | .banner = xen_banner, | 903 | }; |
904 | 904 | ||
905 | static const struct pv_init_ops xen_init_ops __initdata = { | ||
905 | .patch = xen_patch, | 906 | .patch = xen_patch, |
906 | 907 | ||
908 | .banner = xen_banner, | ||
907 | .memory_setup = xen_memory_setup, | 909 | .memory_setup = xen_memory_setup, |
908 | .arch_setup = xen_arch_setup, | 910 | .arch_setup = xen_arch_setup, |
909 | .init_IRQ = xen_init_IRQ, | ||
910 | .post_allocator_init = xen_mark_init_mm_pinned, | 911 | .post_allocator_init = xen_mark_init_mm_pinned, |
912 | }; | ||
911 | 913 | ||
914 | static const struct pv_time_ops xen_time_ops __initdata = { | ||
912 | .time_init = xen_time_init, | 915 | .time_init = xen_time_init, |
916 | |||
913 | .set_wallclock = xen_set_wallclock, | 917 | .set_wallclock = xen_set_wallclock, |
914 | .get_wallclock = xen_get_wallclock, | 918 | .get_wallclock = xen_get_wallclock, |
915 | .get_cpu_khz = xen_cpu_khz, | 919 | .get_cpu_khz = xen_cpu_khz, |
916 | .sched_clock = xen_sched_clock, | 920 | .sched_clock = xen_sched_clock, |
921 | }; | ||
917 | 922 | ||
923 | static const struct pv_cpu_ops xen_cpu_ops __initdata = { | ||
918 | .cpuid = xen_cpuid, | 924 | .cpuid = xen_cpuid, |
919 | 925 | ||
920 | .set_debugreg = xen_set_debugreg, | 926 | .set_debugreg = xen_set_debugreg, |
@@ -925,22 +931,10 @@ static const struct paravirt_ops xen_paravirt_ops __initdata = { | |||
925 | .read_cr0 = native_read_cr0, | 931 | .read_cr0 = native_read_cr0, |
926 | .write_cr0 = native_write_cr0, | 932 | .write_cr0 = native_write_cr0, |
927 | 933 | ||
928 | .read_cr2 = xen_read_cr2, | ||
929 | .write_cr2 = xen_write_cr2, | ||
930 | |||
931 | .read_cr3 = xen_read_cr3, | ||
932 | .write_cr3 = xen_write_cr3, | ||
933 | |||
934 | .read_cr4 = native_read_cr4, | 934 | .read_cr4 = native_read_cr4, |
935 | .read_cr4_safe = native_read_cr4_safe, | 935 | .read_cr4_safe = native_read_cr4_safe, |
936 | .write_cr4 = xen_write_cr4, | 936 | .write_cr4 = xen_write_cr4, |
937 | 937 | ||
938 | .save_fl = xen_save_fl, | ||
939 | .restore_fl = xen_restore_fl, | ||
940 | .irq_disable = xen_irq_disable, | ||
941 | .irq_enable = xen_irq_enable, | ||
942 | .safe_halt = xen_safe_halt, | ||
943 | .halt = xen_halt, | ||
944 | .wbinvd = native_wbinvd, | 938 | .wbinvd = native_wbinvd, |
945 | 939 | ||
946 | .read_msr = native_read_msr_safe, | 940 | .read_msr = native_read_msr_safe, |
@@ -968,7 +962,19 @@ static const struct paravirt_ops xen_paravirt_ops __initdata = { | |||
968 | 962 | ||
969 | .set_iopl_mask = xen_set_iopl_mask, | 963 | .set_iopl_mask = xen_set_iopl_mask, |
970 | .io_delay = xen_io_delay, | 964 | .io_delay = xen_io_delay, |
965 | }; | ||
966 | |||
967 | static const struct pv_irq_ops xen_irq_ops __initdata = { | ||
968 | .init_IRQ = xen_init_IRQ, | ||
969 | .save_fl = xen_save_fl, | ||
970 | .restore_fl = xen_restore_fl, | ||
971 | .irq_disable = xen_irq_disable, | ||
972 | .irq_enable = xen_irq_enable, | ||
973 | .safe_halt = xen_safe_halt, | ||
974 | .halt = xen_halt, | ||
975 | }; | ||
971 | 976 | ||
977 | static const struct pv_apic_ops xen_apic_ops __initdata = { | ||
972 | #ifdef CONFIG_X86_LOCAL_APIC | 978 | #ifdef CONFIG_X86_LOCAL_APIC |
973 | .apic_write = xen_apic_write, | 979 | .apic_write = xen_apic_write, |
974 | .apic_write_atomic = xen_apic_write, | 980 | .apic_write_atomic = xen_apic_write, |
@@ -977,6 +983,17 @@ static const struct paravirt_ops xen_paravirt_ops __initdata = { | |||
977 | .setup_secondary_clock = paravirt_nop, | 983 | .setup_secondary_clock = paravirt_nop, |
978 | .startup_ipi_hook = paravirt_nop, | 984 | .startup_ipi_hook = paravirt_nop, |
979 | #endif | 985 | #endif |
986 | }; | ||
987 | |||
988 | static const struct pv_mmu_ops xen_mmu_ops __initdata = { | ||
989 | .pagetable_setup_start = xen_pagetable_setup_start, | ||
990 | .pagetable_setup_done = xen_pagetable_setup_done, | ||
991 | |||
992 | .read_cr2 = xen_read_cr2, | ||
993 | .write_cr2 = xen_write_cr2, | ||
994 | |||
995 | .read_cr3 = xen_read_cr3, | ||
996 | .write_cr3 = xen_write_cr3, | ||
980 | 997 | ||
981 | .flush_tlb_user = xen_flush_tlb, | 998 | .flush_tlb_user = xen_flush_tlb, |
982 | .flush_tlb_kernel = xen_flush_tlb, | 999 | .flush_tlb_kernel = xen_flush_tlb, |
@@ -986,9 +1003,6 @@ static const struct paravirt_ops xen_paravirt_ops __initdata = { | |||
986 | .pte_update = paravirt_nop, | 1003 | .pte_update = paravirt_nop, |
987 | .pte_update_defer = paravirt_nop, | 1004 | .pte_update_defer = paravirt_nop, |
988 | 1005 | ||
989 | .pagetable_setup_start = xen_pagetable_setup_start, | ||
990 | .pagetable_setup_done = xen_pagetable_setup_done, | ||
991 | |||
992 | .alloc_pt = xen_alloc_pt_init, | 1006 | .alloc_pt = xen_alloc_pt_init, |
993 | .release_pt = xen_release_pt, | 1007 | .release_pt = xen_release_pt, |
994 | .alloc_pd = paravirt_nop, | 1008 | .alloc_pd = paravirt_nop, |
@@ -1023,7 +1037,9 @@ static const struct paravirt_ops xen_paravirt_ops __initdata = { | |||
1023 | .activate_mm = xen_activate_mm, | 1037 | .activate_mm = xen_activate_mm, |
1024 | .dup_mmap = xen_dup_mmap, | 1038 | .dup_mmap = xen_dup_mmap, |
1025 | .exit_mmap = xen_exit_mmap, | 1039 | .exit_mmap = xen_exit_mmap, |
1040 | }; | ||
1026 | 1041 | ||
1042 | static const struct pv_misc_ops xen_misc_ops __initdata = { | ||
1027 | .set_lazy_mode = xen_set_lazy_mode, | 1043 | .set_lazy_mode = xen_set_lazy_mode, |
1028 | }; | 1044 | }; |
1029 | 1045 | ||
@@ -1091,7 +1107,15 @@ asmlinkage void __init xen_start_kernel(void) | |||
1091 | BUG_ON(memcmp(xen_start_info->magic, "xen-3.0", 7) != 0); | 1107 | BUG_ON(memcmp(xen_start_info->magic, "xen-3.0", 7) != 0); |
1092 | 1108 | ||
1093 | /* Install Xen paravirt ops */ | 1109 | /* Install Xen paravirt ops */ |
1094 | paravirt_ops = xen_paravirt_ops; | 1110 | pv_info = xen_info; |
1111 | pv_init_ops = xen_init_ops; | ||
1112 | pv_time_ops = xen_time_ops; | ||
1113 | pv_cpu_ops = xen_cpu_ops; | ||
1114 | pv_irq_ops = xen_irq_ops; | ||
1115 | pv_apic_ops = xen_apic_ops; | ||
1116 | pv_mmu_ops = xen_mmu_ops; | ||
1117 | pv_misc_ops = xen_misc_ops; | ||
1118 | |||
1095 | machine_ops = xen_machine_ops; | 1119 | machine_ops = xen_machine_ops; |
1096 | 1120 | ||
1097 | #ifdef CONFIG_SMP | 1121 | #ifdef CONFIG_SMP |
@@ -1124,9 +1148,9 @@ asmlinkage void __init xen_start_kernel(void) | |||
1124 | xen_setup_vcpu_info_placement(); | 1148 | xen_setup_vcpu_info_placement(); |
1125 | #endif | 1149 | #endif |
1126 | 1150 | ||
1127 | paravirt_ops.kernel_rpl = 1; | 1151 | pv_info.kernel_rpl = 1; |
1128 | if (xen_feature(XENFEAT_supervisor_mode_kernel)) | 1152 | if (xen_feature(XENFEAT_supervisor_mode_kernel)) |
1129 | paravirt_ops.kernel_rpl = 0; | 1153 | pv_info.kernel_rpl = 0; |
1130 | 1154 | ||
1131 | /* set the limit of our address space */ | 1155 | /* set the limit of our address space */ |
1132 | reserve_top_address(-HYPERVISOR_VIRT_START + 2 * PAGE_SIZE); | 1156 | reserve_top_address(-HYPERVISOR_VIRT_START + 2 * PAGE_SIZE); |