paravirt_ops - core changes
Subsystems (2)
A message that is not in the archive (sent off-list or not yet received): [email protected]
PATCH 1/17 paravirt_ops - core changes
plain text document attachment (xx-paravirt-core.patch) Paravirt Ops core files.
arch/x86_64/kernel/paravirt.c new file +504 -0
@@ -0,0 +1,504 @@ +/* Paravirtualization interfaces +Copyright (C) 2007 Glauber de Oliveira Costa, Red Hat Inc. +Based on i386 work by Rusty Russell. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ +#include <linux/errno.h> +#include <linux/module.h> +#include <linux/efi.h> +#include <linux/bcd.h> +#include <linux/start_kernel.h> + +#include <asm/bug.h> +#include <asm/paravirt.h> +#include <asm/desc.h> +#include <asm/setup.h> +#include <asm/irq.h> +#include <asm/delay.h> +#include <asm/fixmap.h> +#include <asm/apic.h> +#include <asm/tlbflush.h> +#include <asm/msr.h> +#include <asm/page.h> +#include <asm/pgtable.h> +#include <asm/proto.h> +#include <asm/time.h> +#include <asm/e820.h> + +/* nop stub */ +void native_nop (void ) +{ +} + +static void __init default_banner (void ) +{ +printk (KERN_INFO "Booting paravirtualized kernel on %s\n" , + paravirt_ops.name); +} + +void memory_setup (void ) +{ + paravirt_ops.memory_setup (); +} + +void syscall_init (void ) +{ + paravirt_ops.syscall_init (); +} + +/* Simple instruction patching code. */ +#define DEF_NATIVE (name, code) \ + extern const char start_##name[], end_##name[]; \ + asm("start_" #name ": " code "; end_" #name ":") +DEF_NATIVE (cli,"cli" ); +DEF_NATIVE (sti,"sti" ); +/* We push rdi , and pop in rda. This is due to x86_64 calling conventions +* Recall that we are patching a function call */ +DEF_NATIVE (popfq,"pushq %rdi; popfq" ); +DEF_NATIVE (pushfq,"pushfq; popq %rax" ); +DEF_NATIVE (pushfq_cli,"pushfq; popq %rax; cli" ); +DEF_NATIVE (iret,"iretq" ); +DEF_NATIVE (sysretq,"sysretq" ); +DEF_NATIVE (swapgs,"swapgs" ); + +static const struct native_insns +{ +const char *start, *end; +} native_insns[] = { + [PARAVIRT_IRQ_DISABLE ] = { start_cli, end_cli }, + [PARAVIRT_IRQ_ENABLE ] = { start_sti, end_sti }, + [PARAVIRT_RESTORE_FLAGS ] = { start_popfq, end_popfq }, + [PARAVIRT_SAVE_FLAGS ] = { start_pushfq, end_pushfq }, + [PARAVIRT_SAVE_FLAGS_IRQ_DISABLE ] = { start_pushfq_cli, end_pushfq_cli }, + [PARAVIRT_INTERRUPT_RETURN ] = { start_iret, end_iret }, + [PARAVIRT_SYSRETQ ] = { start_sysretq, end_sysretq }, + [PARAVIRT_SWAPGS ] = { start_swapgs, end_swapgs }, +}; + +static unsigned native_patch (u8 type,u16 clobbers,void *insns,unsigned len) +{ +unsigned int insn_len; + +/* Don't touch it if we don't have a replacement */ +if (type >=ARRAY_SIZE (native_insns) || !native_insns[type].start) +return len; + + insn_len = native_insns[type].end - native_insns[type].start; + +/* Similarly if we can't fit replacement. */ +if (len < insn_len) +return len; + +memcpy (insns, native_insns[type].start, insn_len); +return insn_len; +} + +static unsigned long native_get_debugreg (int regno) +{ +unsigned long val =0 ;/* Damn you, gcc! */ + +switch (regno) { +case 0 : + asm("movq %%db0, %0" :"=r" (val));break ; +case 1 : + asm("movq %%db1, %0" :"=r" (val));break ; +case 2 : + asm("movq %%db2, %0" :"=r" (val));break ; +case 3 : + asm("movq %%db3, %0" :"=r" (val));break ; +case 6 : + asm("movq %%db6, %0" :"=r" (val));break ; +case 7 : + asm("movq %%db7, %0" :"=r" (val));break ; +default : +BUG (); + } +return val; +} + +static void native_set_debugreg (int regno,unsigned long value) +{ +switch (regno) { +case 0 : + asm("movq %0,%%db0" :/* no output */ :"r" (value)); +break ; +case 1 : + asm("movq %0,%%db1" :/* no output */ :"r" (value)); +break ; +case 2 : + asm("movq %0,%%db2" :/* no output */ :"r" (value)); +break ; +case 3 : + asm("movq %0,%%db3" :/* no output */ :"r" (value)); +break ; +case 6 : + asm("movq %0,%%db6" :/* no output */ :"r" (value)); +break ; +case 7 : + asm("movq %0,%%db7" :/* no output */ :"r" (value)); +break ; +default : +BUG (); + } +} + +void init_IRQ (void ) +{ + paravirt_ops.init_IRQ (); +} + +static unsigned long native_save_fl (void ) +{ +unsigned long f; + asmvolatile ("pushfq ; popq %0" :"=g" (f):/* no input */ ); +return f; +} + +static void native_restore_fl (unsigned long f) +{ + asmvolatile ("pushq %0 ; popfq" :/* no output */ + :"g" (f) + :"memory" ,"cc" ); +} + +static void native_irq_disable (void ) +{ + asmvolatile ("cli" : : :"memory" ); +} + +static void native_irq_enable (void ) +{ + asmvolatile ("sti" : : :"memory" ); +} + +static void native_safe_halt (void ) +{ + asmvolatile ("sti; hlt" : : :"memory" ); +} + +static void native_halt (void ) +{ + asmvolatile ("hlt" : : :"memory" ); +} + +static u64 native_read_tsc (void ) +{ +unsigned long a, b; + asmvolatile ("rdtsc" :"=a" (a),"=d" (b)); +return a | (b <<32 ); +} + +static u64 native_read_tscp (int *aux) +{ +u64 a, b; + asmvolatile ("rdtscp" :"=a" (a),"=b" (b),"=c" (aux)); +return a | (b <<32 ); +} + +static u64 native_read_pmc (void ) +{ +unsigned long a, b; + asmvolatile ("rdpmc" :"=a" (a),"=b" (b)); +return a | (b <<32 ); +} + +static void native_store_gdt (struct desc_ptr *dtr) +{ + asm ("sgdt %w0" :"=m" (*dtr)); +} + +static void native_store_idt (struct desc_ptr *dtr) +{ + asm ("sidt %w0" :"=m" (*dtr)); +} + +static unsigned long native_store_tr (void ) +{ +unsigned long tr; + asm ("str %w0" :"=r" (tr)); +return tr; +} + +static void native_load_tls (struct thread_struct *t,unsigned int cpu) +{ +u64 *gdt = (u64 *)(cpu_gdt (cpu) +GDT_ENTRY_TLS_MIN ); + gdt[0 ] = t->tls_array[0 ]; + gdt[1 ] = t->tls_array[1 ]; + gdt[2 ] = t->tls_array[2 ]; +} + +static inline void native_write_dt_entry (void *dt,int entry,u32 entry_low,u32 entry_high) +{ +u32 *lp = (u32 *)((char *)dt + entry*8 ); + lp[0 ] = entry_low; + lp[1 ] = entry_high; +} + +static void native_write_ldt_entry (void *dt,int entrynum,u32 low,u32 high) +{ +native_write_dt_entry (dt, entrynum, low, high); +} + +static void native_write_gdt_entry (void *dt,int entrynum,u32 low,u32 high) +{ +native_write_dt_entry (dt, entrynum, low, high); +} + +static void native_write_idt_entry (void *dt,int entrynum,u32 low,u32 high) +{ +native_write_dt_entry (dt, entrynum, low, high); +} + +static void native_load_rsp0 (struct tss_struct *tss, +struct thread_struct *thread) +{ + tss->rsp0 = thread->rsp0; +} + +static void native_io_delay (void ) +{ + asmvolatile ("outb %al,$0x80" ); +} + +void native_pagetable_setup_start (pgd_t *base) +{ +int i; + +/* +* Init entries of the first-level page table to the +* zero page, if they haven't already been set up. +* +* In a normal native boot, we'll be running on a +* pagetable rooted in swapper_pg_dir, but not in PAE +* mode, so this will end up clobbering the mappings +* for the lower 24Mbytes of the address space, +* without affecting the kernel address space. +*/ +for (i =0 ; i <USER_PTRS_PER_PGD ; i++) +set_pgd (&base[i], +__pgd (__pa (empty_zero_page) | _PAGE_PRESENT)); +memset (&base[USER_PTRS_PER_PGD ],0 ,sizeof (pgd_t)); +} + +void native_pagetable_setup_done (pgd_t *base) +{ +/* +* Add low memory identity-mappings - SMP needs it when +* starting up on an AP from real-mode. In the non-PAE +* case we already have these mappings through head.S. +* All user-space mappings are explicitly cleared after +* SMP startup. +*/ +set_pgd (&base[0 ], base[USER_PTRS_PER_PGD ]); +} + + +static void native_flush_tlb (void ) +{ +__native_flush_tlb (); +} + +/* +* Global pages have to be flushed a bit differently. Not a real +* performance problem because this does not happen often. +*/ +static void native_flush_tlb_all (void ) +{ +__native_flush_tlb_all (); +} + +static void native_flush_tlb_one (u64 addr) +{ +__native_flush_tlb_one (addr); +} + +pte_t native_make_pte (unsigned long pte) +{ +return (pte_t ){ pte }; +} + +pud_t native_make_pud (unsigned long pud) +{ +return (pud_t ){ pud }; +} + +pmd_t native_make_pmd (unsigned long pmd) +{ +return (pmd_t ){ pmd }; +} + +pgd_t native_make_pgd (unsigned long pgd) +{ +return (pgd_t ){ pgd }; +} + +pte_t native_ptep_get_and_clear (struct mm_struct *mm,u64 addr, +pte_t *ptep) +{ +return __pte (xchg (&(ptep)->pte,0 )); +} + +void native_set_pte_at (struct mm_struct *mm,u64 addr,pte_t *ptep, +pte_t pteval) +{ +native_set_pte (ptep,pteval); +} + +void native_pte_clear (struct mm_struct *mm,u64 addr,pte_t *ptep) +{ +native_set_pte_at (mm,addr,ptep,__pte (0 )); +} + +void native_pmd_clear (pmd_t *pmd) +{ +native_set_pmd (pmd,__pmd (0 )); +} + +void native_swapgs (unsigned long rip) +{ + asmvolatile ("swapgs" :: :"memory" ); +} + +/* These are in entry.S */ +extern void native_iret (void ); +extern void native_sysret (void ); + +static int __init print_banner (void ) +{ + paravirt_ops.banner (); +return 0 ; +} +core_initcall (print_banner); + +/* We simply declare start_kernel to be the paravirt probe of last resort. */ +paravirt_probe_failsafe (start_kernel); + +extern unsigned long __vsyscall_0; +struct paravirt_ops paravirt_ops = { + .name ="bare hardware" , + .mem_type ="BIOS-e820" , + .paravirt_enabled =0 , + .pgd_alignment =sizeof (pgd_t) *PTRS_PER_PGD , + + .vsyscall_page = &__vsyscall_0, + .patch = native_patch, + .banner = default_banner, + .arch_setup = native_nop, + .memory_setup = setup_memory_region, + .syscall_init = x86_64_syscall_init, + .get_wallclock = do_get_cmos_time, + .set_wallclock = do_set_rtc_mmss, + .time_init = time_init_hook, + .init_IRQ = native_init_IRQ, + + .cpuid = native_cpuid, + .get_debugreg = native_get_debugreg, + .set_debugreg = native_set_debugreg, + .clts = native_clts, + .read_cr0 = native_read_cr0, + .write_cr0 = native_write_cr0, + .read_cr2 = native_read_cr2, + .write_cr2 = native_write_cr2, + .read_cr3 = native_read_cr3, + .write_cr3 = native_write_cr3, + .read_cr4 = native_read_cr4, + .write_cr4 = native_write_cr4, + .save_fl = native_save_fl, + .restore_fl = native_restore_fl, + .irq_disable = native_irq_disable, + .irq_enable = native_irq_enable, + .safe_halt = native_safe_halt, + .halt = native_halt, + .wbinvd = native_wbinvd, + .read_msr = native_read_msr_safe, + .write_msr = native_write_msr_safe, + .read_tsc = native_read_tsc, + .read_tscp = native_read_tscp, + .read_pmc = native_read_pmc, + .load_tr_desc = native_load_tr_desc, + .set_ldt = native_set_ldt, + .load_gdt = native_load_gdt, + .load_idt = native_load_idt, + .store_gdt = native_store_gdt, + .store_idt = native_store_idt, + .store_tr = native_store_tr, + .load_tls = native_load_tls, + .write_ldt_entry = native_write_ldt_entry, + .write_gdt_entry = native_write_gdt_entry, + .write_idt_entry = native_write_idt_entry, + .load_rsp0 = native_load_rsp0, + + .io_delay = native_io_delay, + .const_udelay = __const_udelay, + +#ifdef CONFIG_X86_LOCAL_APIC + .apic_write = native_apic_write, + .apic_read = native_apic_read, +#endif + .set_lazy_mode = (void *)native_nop, + .ebda_info = native_ebda_info, + + .pagetable_setup_start = native_pagetable_setup_start, + .pagetable_setup_done = native_pagetable_setup_done, + + .flush_tlb_user = native_flush_tlb, + .flush_tlb_kernel = native_flush_tlb_all, + .flush_tlb_single = native_flush_tlb_one, + + .alloc_pt = (void *)native_nop, + .alloc_pd = (void *)native_nop, + .alloc_pd_clone = (void *)native_nop, + .release_pt = (void *)native_nop, + .release_pd = (void *)native_nop, + + .set_pte = native_set_pte, + .set_pte_at = native_set_pte_at, + .set_pmd = native_set_pmd, + .set_pud = native_set_pud, + .set_pgd = native_set_pgd, + + .pte_update = (void *)native_nop, + .pte_update_defer = (void *)native_nop, + + .ptep_get_and_clear = native_ptep_get_and_clear, + + .pte_clear = native_pte_clear, + .pmd_clear = native_pmd_clear, + .pud_clear = native_pud_clear, + .pgd_clear = native_pgd_clear, + + .pte_val = native_pte_val, + .pud_val = native_pud_val, + .pmd_val = native_pmd_val, + .pgd_val = native_pgd_val, + + .make_pte = native_make_pte, + .make_pmd = native_make_pmd, + .make_pud = native_make_pud, + .make_pgd = native_make_pgd, + + .swapgs = native_swapgs, + .sysret = native_sysret, + .iret = native_iret, + + .dup_mmap = (void *)native_nop, + .exit_mmap = (void *)native_nop, + .activate_mm = (void *)native_nop, + + .startup_ipi_hook = (void *)native_nop, +}; + +EXPORT_SYMBOL (paravirt_ops);
include/asm-x86_64/paravirt.h new file +678 -0
678 lines not on this page · raw message
arch/x86_64/kernel/Makefile +2 -0
@@ -41,6 +41,8 @@ obj-$(CONFIG_AUDIT) += audit.o obj-$(CONFIG_MODULES) += module.o obj-$(CONFIG_PCI) += early-quirks.o +obj-$(CONFIG_PARAVIRT) += paravirt.o + obj-y += topology.o obj-y += intel_cacheinfo.o
--
PATCH 2/17 paravirt_ops - msr
In reply to a message not in the archiveplain text document attachment (xx-paravirt-msr-header.patch) Code consolidations of msr routines for paravirt ops.
include/asm-x86_64/msr.h +105 -77
@@ -2,6 +2,62 @@#define X86_64_MSR_H 1#ifndef __ASSEMBLY__ +#include <asm/errno.h> + +static inline void native_cpuid (unsigned int *eax,unsigned int *ebx, +unsigned int *ecx,unsigned int *edx) +{ + __asm__("cpuid" + :"=a" (*eax), +"=b" (*ebx), +"=c" (*ecx), +"=d" (*edx) + :"0" (*eax),"2" (*ecx)); +} + +/* wrmsr with exception handling */ +static inline int native_write_msr_safe (unsigned int msr,unsigned long val) +{ +int err; + asmvolatile ("2: wrmsr ; xorl %0,%0\n" +"1:\n\t" +".section .fixup,\"ax\"\n\t" +"3: movl %4,%0 ; jmp 1b\n\t" +".previous\n\t" +".section __ex_table,\"a\"\n" +" .align 8\n\t" +" .quad 2b,3b\n\t" +".previous" + :"=a" (err) + :"c" (msr),"0" ((u32 )val),"d" ((u32)(val>>32 )), +"i" (-EFAULT )); +return err; +} + +/* rdmsr with exception handling */ +static inline unsigned long native_read_msr_safe (unsigned int msr,int *err) +{ +unsigned long a, b; + + asmvolatile ("1: rdmsr\n" +"2:\n" +".section .fixup,\"ax\"\n" +"3: movl %4,%0\n" +" jmp 2b\n" +".previous\n" +".section __ex_table,\"a\"\n" +" .align 8\n" +" .quad 1b,3b\n" +".previous" :"=&bDS" (*err),"=a" (a),"=d" (b) + :"c" (msr),"i" (-EIO ),"0" (0 )); +return a | (b <<32 ); +} + +#ifdef CONFIG_PARAVIRT +#include <asm/paravirt.h> +#else + +#define __cpuid native_cpuid/* * Access to machine-specific registers (available on 586 and better only) * Note: the rd* operations modify the parameters directly (without using
@@ -28,37 +84,18 @@#define wrmsrl (msr,val) wrmsr(msr,(__u32)((__u64)(val)),((__u64)(val))>>32) -/* wrmsr with exception handling */ -#define wrmsr_safe (msr,a,b) ({ int ret__; \ - asm volatile("2: wrmsr ; xorl %0,%0\n" \ - "1:\n\t" \ - ".section .fixup,\"ax\"\n\t" \ - "3: movl %4,%0 ; jmp 1b\n\t" \ - ".previous\n\t" \ - ".section __ex_table,\"a\"\n" \ - " .align 8\n\t" \ - " .quad 2b,3b\n\t" \ - ".previous" \ - : "=a" (ret__) \ - : "c" (msr), "0" (a), "d" (b), "i" (-EFAULT)); \ - ret__; }) - -#define checking_wrmsrl (msr,val) wrmsr_safe(msr,(u32)(val),(u32)((val)>>32)) - -#define rdmsr_safe (msr,a,b) \ - ({ int ret__; \ - asm volatile ("1: rdmsr\n" \ - "2:\n" \ - ".section .fixup,\"ax\"\n" \ - "3: movl %4,%0\n" \ - " jmp 2b\n" \ - ".previous\n" \ - ".section __ex_table,\"a\"\n" \ - " .align 8\n" \ - " .quad 1b,3b\n" \ - ".previous":"=&bDS" (ret__), "=a"(*(a)), "=d"(*(b))\ - :"c"(msr), "i"(-EIO), "0"(0)); \ - ret__; }) +#define wrmsr_safe (msr,val1,val2) \ + native_write_msr_safe(msr,(u64)(val1)|(u64)(val2)<<32) + +#define rdmsr_safe (msr,val1,val2) \ + ({ \ + int __err; \ + unsigned long __val; \ + __val = native_read_msr_safe(msr, &__err); \ + *val1 = (u32)__val; \ + *val2 = (u32)(__val>>32); \ + __err; \ + })#define rdtsc (low,high) \ __asm__ __volatile__("rdtsc" : "=a" (low), "=d" (high))
@@ -66,8 +103,6 @@#define rdtscl (low) \ __asm__ __volatile__ ("rdtsc" : "=a" (low) : : "edx") -#define rdtscp (low,high,aux) \ - asm volatile (".byte 0x0f,0x01,0xf9" : "=a" (low), "=d" (high), "=c" (aux))#define rdtscll (val) do { \ unsigned int __a,__d; \
@@ -75,42 +110,43 @@ (val) = ((unsigned long )__a) | (((unsigned long )__d)<<32 ); \ } while(0) +#define rdpmc (counter,low,high) \ + __asm__ __volatile__("rdpmc" \ + : "=a" (low), "=d" (high) \ + : "c" (counter)) + +#define rdtscp (low,high,aux) \ + asm volatile (".byte 0x0f,0x01,0xf9" : "=a" (low), "=d" (high), "=c" (aux)) +#define rdtscpll (val, aux) do { \ unsigned long __a, __d; \ asm volatile (".byte 0x0f,0x01,0xf9" : "=a" (__a), "=d" (__d), "=c" (aux)); \ (val) = (__d << 32) | __a; \ } while (0) +#define checking_wrmsrl (msr,val) native_write_msr_safe(msr, val) + +#endif /* CONFIG_PARAVIRT */ +#define write_tsc (val1,val2) wrmsr(0x10, val1, val2)#define write_rdtscp_aux (val) wrmsr(0xc0000103, val, 0) -#define rdpmc (counter,low,high) \ - __asm__ __volatile__("rdpmc" \ - : "=a" (low), "=d" (high) \ - : "c" (counter)) - -static inline void cpuid (int op,unsigned int *eax,unsigned int *ebx, +static inline void cpuid (unsigned int op,unsigned int *eax,unsigned int *ebx,unsigned int *ecx,unsigned int *edx) { - __asm__("cpuid" - :"=a" (*eax), -"=b" (*ebx), -"=c" (*ecx), -"=d" (*edx) - :"0" (op)); + *eax = op; + *ecx =0 ; +__cpuid (eax, ebx, ecx, edx); }/* Some CPUID calls want 'count' to be placed in ecx */ -static inline void cpuid_count (int op,int count,int *eax,int *ebx,int *ecx, -int *edx) +static inline void cpuid_count (int op,int count, +int *eax,int *ebx,int *ecx,int *edx) { - __asm__("cpuid" - :"=a" (*eax), -"=b" (*ebx), -"=c" (*ecx), -"=d" (*edx) - :"0" (op),"c" (count)); + *eax = op; + *ecx = count; +__cpuid (eax, ebx, ecx, edx); }/*
@@ -118,42 +154,34 @@ static inline void cpuid_count(int op, i*/ static inline unsigned int cpuid_eax (unsigned int op) { -unsigned int eax; - - __asm__("cpuid" - :"=a" (eax) - :"0" (op) - :"bx" ,"cx" ,"dx" ); +unsigned int eax, ebx, ecx, edx; + eax = op; + ecx =0 ; +__cpuid (&eax, &ebx, &ecx, &edx);return eax; }static inline unsigned int cpuid_ebx (unsigned int op) { -unsigned int eax, ebx; - - __asm__("cpuid" - :"=a" (eax),"=b" (ebx) - :"0" (op) - :"cx" ,"dx" ); +unsigned int eax, ebx, ecx, edx; + eax = op; + ecx =0 ; +__cpuid (&eax, &ebx, &ecx, &edx);return ebx; }static inline unsigned int cpuid_ecx (unsigned int op) { -unsigned int eax, ecx; - - __asm__("cpuid" - :"=a" (eax),"=c" (ecx) - :"0" (op) - :"bx" ,"dx" ); +unsigned int eax, ebx, ecx, edx; + eax = op; + ecx =0 ; +__cpuid (&eax, &ebx, &ecx, &edx);return ecx; }static inline unsigned int cpuid_edx (unsigned int op) { -unsigned int eax, edx; - - __asm__("cpuid" - :"=a" (eax),"=d" (edx) - :"0" (op) - :"bx" ,"cx" ); +unsigned int eax, ebx, ecx, edx; + eax = op; + ecx =0 ; +__cpuid (&eax, &ebx, &ecx, &edx);return edx; }
--
PATCH 3/17 paravirt_ops - system routines
In reply to a message not in the archiveplain text document attachment (xx-paravirt-processor-header.patch) System routine updates for the paravirt_ops interface.
include/asm-x86_64/processor.h +29 -29
@@ -139,35 +139,6 @@ extern unsigned short num_cache_leaves;#define X86_CR4_OSXMMEXCPT 0x0400/* enable unmasked SSE exceptions */ /* -* Save the cr4 feature set we're using (ie -* Pentium 4MB enable and PPro Global page -* enable), so that any CPU's that boot up -* after us can get the correct flags. -*/ -extern unsigned long mmu_cr4_features; - -static inline void set_in_cr4 (unsigned long mask) -{ - mmu_cr4_features |= mask; - __asm__("movq %%cr4,%%rax\n\t" -"orq %0,%%rax\n\t" -"movq %%rax,%%cr4\n" - : :"irg" (mask) - :"ax" ); -} - -static inline void clear_in_cr4 (unsigned long mask) -{ - mmu_cr4_features &= ~mask; - __asm__("movq %%cr4,%%rax\n\t" -"andq %0,%%rax\n\t" -"movq %%rax,%%cr4\n" - : :"irg" (~mask) - :"ax" ); -} - - -/* * User space process size. 47bits minus one guard page. */ #define TASK_SIZE64 (0x800000000000UL - 4096)
@@ -299,6 +270,10 @@ struct thread_struct {set_fs (USER_DS ); \ } while(0) +#ifdef CONFIG_PARAVIRT +#include <asm/paravirt.h> +#else +#define paravirt_enabled () 0#define get_debugreg (var, register) \ __asm__("movq %%db" #register ", %0" \ :"=r" (var))
@@ -306,6 +281,31 @@ struct thread_struct { __asm__("movq %0,%%db" #register \ :/* no output */ \ :"r" (value)) +#define load_rsp0 (tss, thread) \ + do { (tss)->rsp0 = (thread)->rsp0; } while(0) +#endif + +/* +* Save the cr4 feature set we're using (ie +* Pentium 4MB enable and PPro Global page +* enable), so that any CPU's that boot up +* after us can get the correct flags. +*/ +extern unsigned long mmu_cr4_features; + +static inline void set_in_cr4 (unsigned long mask) +{ + mmu_cr4_features |= mask; +write_cr4 (read_cr4 () | mask); +} + +static inline void clear_in_cr4 (unsigned long mask) +{ + mmu_cr4_features &= ~mask; +write_cr4 (read_cr4 () & ~mask); +} + +struct task_struct ;struct mm_struct ;
include/asm-x86_64/system.h +72 -34
118 lines not on this page · raw message
--
PATCH 4/17 pavarvirt_ops - apci header updates
In reply to a message not in the archiveplain text document attachment (xx-paravirt-apic-header.patch) This patch updates the apic header file for switching apic_read and write for use with paravirt ops.
include/asm-x86_64/apic.h +10 -2
@@ -37,16 +37,24 @@ struct pt_regs;* Basic functions accessing APICs. */ -static __inlinevoid apic_write (unsigned long reg,unsigned int v) +static __inlinevoid native_apic_write (unsigned long reg,unsigned int v) { *((volatile unsigned int *)(APIC_BASE +reg)) = v; } -static __inlineunsigned int apic_read (unsigned long reg) +static __inlineunsigned int native_apic_read (unsigned long reg) {return *((volatile unsigned int *)(APIC_BASE +reg)); } +#ifdef CONFIG_PARAVIRT +#include <asm/paravirt.h> +#else +#define apic_write native_apic_write +#define apic_read native_apic_read + +#endif /* CONFIG_PARAVIRT */ +static __inline__void apic_wait_icr_idle (void ) {while (apic_read (APIC_ICR ) &APIC_ICR_BUSY )
--
PATCH 5/17 pravirt_ops - segments
In reply to a message not in the archiveplain text document attachment (xx-paravirt-segment-header.patch) Added two new segments for the hypervisor.
include/asm-x86_64/segment.h +7 -1
@@ -37,8 +37,14 @@#define GS_TLS_SEL ((GDT_ENTRY_TLS_MIN+GS_TLS)*8 + 3)#define FS_TLS_SEL ((GDT_ENTRY_TLS_MIN+FS_TLS)*8 + 3) +#define __HV_CS 0x80/* 16*8 */ +#define __HV_DS 0x88/* 17*8 */ + +#define GDT_ENTRY_HV_CS 16 +#define GDT_ENTRY_HV_DS 17 +#define IDT_ENTRIES 256 -#define GDT_ENTRIES 16 +#define GDT_ENTRIES 18#define GDT_SIZE (GDT_ENTRIES * 8)#define TLS_SIZE (GDT_ENTRY_TLS_ENTRIES * 8)
--
Re: [RFC/PATCH PV_OPS X86_64 05/17] pravirt_ops - segments
include/asm-x86_64/segment.h line 45
Quoted 12 lines · * Steven Rostedt ([email protected]) wrote:
include/asm-x86_64/segment.h +6
-0@@ -37,8 +37,14 @@#define GS_TLS_SEL ((GDT_ENTRY_TLS_MIN+GS_TLS)*8 + 3)#define FS_TLS_SEL ((GDT_ENTRY_TLS_MIN+FS_TLS)*8 + 3) +#define __HV_CS 0x80/* 16*8 */ +#define __HV_DS 0x88/* 17*8 */ + +#define GDT_ENTRY_HV_CS 16 +#define GDT_ENTRY_HV_DS 17 +
Hmm, this one is not technically needed for pv_ops, looks like lguest bleeding in ;-)
Re: [RFC/PATCH PV_OPS X86_64 05/17] pravirt_ops - segments
Quoted 7 lines · Chris Wright
Quoted 6 lines · * Steven Rostedt ([email protected]) wrote:
include/asm-x86_64/segment.h +0
-0@@ -37,8 +37,14 @@#define GS_TLS_SEL ((GDT_ENTRY_TLS_MIN+GS_TLS)*8 + 3)#define FS_TLS_SEL ((GDT_ENTRY_TLS_MIN+FS_TLS)*8 + 3)
Quoted 9 lines
include/asm-x86_64/segment.h line 45
Quoted 6 lines
include/asm-x86_64/segment.h +6
-0+#define __HV_CS 0x80/* 16*8 */ +#define __HV_DS 0x88/* 17*8 */ + +#define GDT_ENTRY_HV_CS 16 +#define GDT_ENTRY_HV_DS 17 +Hmm, this one is not technically needed for
pv_ops, looks like lguest bleeding in ;-)
I thought this could be HV agnostic, so I slipped it in. But that's questionable, and hence, its own separate patch.
-- Steve
PATCH 6/17 paravirt_op - miscellaneous updates.
In reply to a message not in the archiveplain text document attachment (xx-paravirt-misc-headers.patch) Miscellaneous header updates. Sort of a work-in-progress.
include/asm-x86_64/proto.h +4 -0
@@ -27,7 +27,11 @@ extern void init_memory_mapping(unsignedextern void system_call (void );extern int kernel_syscall (void ); +#ifdef CONFIG_PARAVIRT +extern void x86_64_syscall_init (void ); +#else extern void syscall_init (void ); +#endif extern void ia32_syscall (void );extern void ia32_cstar_target (void );
include/asm-x86_64/spinlock.h +4 -0
@@ -6,6 +6,10 @@#include <asm/page.h> #include <asm/processor.h> +#ifdef CONFIG_PARAVIRT +#include <asm/paravirt.h> +#endif +/* * Your basic SMP spinlocks, allowing only a single CPU anywhere *
--
PATCH 7/17 paravirt_ops - descriptor changes.
In reply to a message not in the archiveplain text document attachment (xx-paravirt-desc-header.patch) Update the descriptors for an interface with paravirt ops
include/asm-x86_64/desc.h +51 -20
@@ -16,9 +16,8 @@extern struct desc_struct cpu_gdt_table[GDT_ENTRIES ]; -#define load_TR_desc () asm volatile("ltr %w0"::"r" (GDT_ENTRY_TSS*8)) -#define load_LDT_desc () asm volatile("lldt %w0"::"r" (GDT_ENTRY_LDT*8)) -#define clear_LDT () asm volatile("lldt %w0"::"r" (0)) +/* the cpu gdt accessor */ +#define cpu_gdt (_cpu) ((struct desc_struct *)cpu_gdt_descr[_cpu].address)/* * This is the ldt that every process will get unless we need
@@ -28,8 +27,6 @@ extern struct desc_struct default_ldt[];extern struct gate_struct idt_table[];extern struct desc_ptr cpu_gdt_descr[]; -/* the cpu gdt accessor */ -#define cpu_gdt (_cpu) ((struct desc_struct *)cpu_gdt_descr[_cpu].address)static inline void _set_gate (void *adr,unsigned type,unsigned long func,unsigned dpl,unsigned ist) {
@@ -115,7 +112,35 @@ static inline void set_seg_base(unsigned d->base0 = addr &0xffff ; d->base1 = (addr >>16 ) &0xff ; d->base2 = (addr >>24 ) &0xff ; -} +} + +static inline void native_load_tr_desc (void ) +{ + asmvolatile ("ltr %w0" ::"r" (GDT_ENTRY_TSS *8 )); +} + +static inline void native_load_gdt (const struct desc_ptr *dtr) +{ + asmvolatile ("lgdt %w0" ::"m" (*dtr)); +} + +static inline void native_load_idt (const struct desc_ptr *dtr) +{ + asmvolatile ("lidt %w0" ::"m" (*dtr)); +} + +#ifdef CONFIG_PARAVIRT +#include <asm/paravirt.h> +#else +#define load_idt native_load_idt +#define load_gdt native_load_gdt +#define load_TR_desc native_load_tr_desc +#define set_ldt native_set_ldt +#define load_TLS native_load_TLS +#endif /* CONFIG_PARAVIRT */ + +#define clear_LDT () set_ldt(NULL,0) +#define LDT_entry_a (info) \ ((((info)->base_addr & 0x0000ffff) << 16) | ((info)->limit & 0x0ffff))
@@ -149,7 +174,7 @@ static inline void set_seg_base(unsigned# error update this code.#endif -static inline void load_TLS (struct thread_struct *t,unsigned int cpu) +static inline void native_load_TLS (struct thread_struct *t,unsigned int cpu) {u64 *gdt = (u64 *)(cpu_gdt (cpu) +GDT_ENTRY_TLS_MIN ); gdt[0 ] = t->tls_array[0 ];
@@ -157,27 +182,33 @@ static inline void load_TLS(struct threa gdt[2 ] = t->tls_array[2 ]; } +static inline void native_set_ldt (const void *addr, +unsigned int entries) +{ +if (likely (entries ==0 )) + __asm__ __volatile__ ("lldt %w0" ::"r" (0 )); +else { +unsigned cpu =smp_processor_id (); + +set_tssldt_descriptor (&cpu_gdt (cpu)[GDT_ENTRY_LDT ], (unsigned long )addr, +DESC_LDT , entries *8 -1 ); + __asm__ __volatile__ ("lldt %w0" ::"r" (GDT_ENTRY_LDT *8 )); + } +} +/* * load one particular LDT into the current CPU */ -static inline void load_LDT_nolock (mm_context_t *pc,int cpu) +static inline void load_LDT_nolock (mm_context_t *pc) { -int count = pc->size; - -if (likely (!count)) { -clear_LDT (); -return ; - } - -set_ldt_desc (cpu, pc->ldt, count); -load_LDT_desc (); +set_ldt (pc->ldt, pc->size); }static inline void load_LDT (mm_context_t *pc) { -int cpu =get_cpu (); -load_LDT_nolock (pc, cpu); -put_cpu (); +preempt_disable (); +load_LDT_nolock (pc); +preempt_enable (); }extern struct desc_ptr idt_descr;
include/asm-x86_64/desc_defs.h +5 -0
@@ -43,6 +43,11 @@ struct gate_struct {#define PTR_MIDDLE (x) (((unsigned long)(x) >> 16) & 0xFFFF)#define PTR_HIGH (x) ((unsigned long)(x) >> 32) +#define DESC_ADDRESS (d) ((unsigned long)((unsigned long)d.base2 << 32) \ + | (d.base1 << 16) | d.base0) + +#define GATE_ADDRESS (g) ((unsigned long)((unsigned long)g.offset_high << 32) \ + | (g.offset_middle << 16) | g.offset_low)enum {DESC_TSS =0x9 ,DESC_LDT =0x2 ,
--
PATCH 8/17 paravirt_ops - memory managment
In reply to a message not in the archiveplain text document attachment (xx-paravirt-mm.patch) Memory management for paravirt_ops.
arch/x86_64/mm/fault.c +2 -2
@@ -180,7 +180,7 @@ void dump_pagetable(unsigned long addrespmd_t *pmd;pte_t *pte; - asm("movq %%cr3,%0" :"=r" (pgd)); + pgd = (pgd_t *)read_cr3 (); pgd =__va ((unsigned long )pgd &PHYSICAL_PAGE_MASK ); pgd +=pgd_index (address);
@@ -347,7 +347,7 @@ asmlinkage void __kprobes do_page_fault(prefetchw (&mm->mmap_sem);/* get the address */ - __asm__("movq %%cr2,%0" :"=r" (address)); + address =read_cr2 (); info.si_code =SEGV_MAPERR ;
arch/x86_64/mm/init.c +2 -2
@@ -384,7 +384,7 @@ void __meminit init_memory_mapping(unsig }if (!after_bootmem) - asmvolatile ("movq %%cr4,%0" :"=r" (mmu_cr4_features)); + mmu_cr4_features =read_cr4 ();__flush_tlb_all (); }
@@ -398,7 +398,7 @@ void __cpuinit zap_low_mappings(int cpu)* For AP's, zap the low identity mappings by changing the cr3 * to init_level4_pgt and doing local flush tlb all */ - asmvolatile ("movq %0,%%cr3" ::"r" (__pa_symbol (&init_level4_pgt))); +write_cr3 (__pa_symbol (&init_level4_pgt)); }__flush_tlb_all (); }
include/asm-x86_64/mmu_context.h +2 -2
@@ -42,7 +42,7 @@ static inline void switch_mm(struct mm_sload_cr3 (next->pgd);if (unlikely (next->context.ldt != prev->context.ldt)) -load_LDT_nolock (&next->context, cpu); +load_LDT_nolock (&next->context); }#ifdef CONFIG_SMP else {
@@ -55,7 +55,7 @@ static inline void switch_mm(struct mm_s* to make sure to use no freed page tables. */ load_cr3 (next->pgd); - load_LDT_nolock(&next->context, cpu); + load_LDT_nolock(&next->context); } }#endif
include/asm-x86_64/page.h +29 -1
@@ -64,16 +64,44 @@ typedef struct { unsigned long pgd; } pgtypedef struct {unsigned long pgprot; }pgprot_t ; +static inline unsigned long native_pte_val (pte_t pte) +{ +return pte.pte; +} + +static inline unsigned long native_pud_val (pud_t pud) +{ +return pud.pud; +} + + +static inline unsigned long native_pmd_val (pmd_t pmd) +{ +return pmd.pmd; +} + +static inline unsigned long native_pgd_val (pgd_t pgd) +{ +return pgd.pgd; +} + + +#ifdef CONFIG_PARAVIRT +#include <asm/paravirt.h> +#else +#define pte_val (x) ((x).pte)#define pmd_val (x) ((x).pmd)#define pud_val (x) ((x).pud)#define pgd_val (x) ((x).pgd) -#define pgprot_val (x) ((x).pgprot)#define __pte (x) ((pte_t) { (x) } )#define __pmd (x) ((pmd_t) { (x) } )#define __pud (x) ((pud_t) { (x) } )#define __pgd (x) ((pgd_t) { (x) } ) +#endif /* CONFIG_PARAVIRT */ + +#define pgprot_val (x) ((x).pgprot)#define __pgprot (x) ((pgprot_t) { (x) } )#define __PHYSICAL_START ((unsigned long)CONFIG_PHYSICAL_START)
include/asm-x86_64/pgtable.h +53 -42
147 lines not on this page · raw message
include/asm-x86_64/tlbflush.h +11 -3
@@ -4,6 +4,7 @@#include <linux/mm.h> #include <asm/processor.h> +static inline unsigned long get_cr3 (void ) {unsigned long cr3;
@@ -16,7 +17,7 @@ static inline void set_cr3(unsigned long asmvolatile ("mov %0,%%cr3" ::"r" (cr3) :"memory" ); } -static inline void __flush_tlb (void ) +static inline void __native_flush_tlb (void ) {set_cr3 (get_cr3 ()); }
@@ -33,17 +34,24 @@ static inline void set_cr4(unsigned long asmvolatile ("mov %0,%%cr4" ::"r" (cr4) :"memory" ); } -static inline void __flush_tlb_all (void ) +static inline void __native_flush_tlb_all (void ) {unsigned long cr4 =get_cr4 ();set_cr4 (cr4 & ~X86_CR4_PGE );/* clear PGE */ set_cr4 (cr4);/* write old PGE again and flush TLBs */ } -#define __flush_tlb_one (addr) \ +#define __native_flush_tlb_one (addr) \ __asm__ __volatile__("invlpg (%0)" :: "r" (addr) : "memory") +#ifdef CONFIG_PARAVIRT +#include <asm/paravirt.h> +#else +#define __flush_tlb __native_flush_tlb +#define __flush_tlb_one __native_flush_tlb_one +#define __flush_tlb_all __native_flush_tlb_all +#endif /* CONFIG_PARAVIRT */ /* * TLB flushing: *
--
PATCH 9/17 paravirt_ops - bios changes
In reply to a message not in the archiveplain text document attachment (xx-paravirt-bios.patch) Add an interface for paravirt ops and e820.
arch/x86_64/kernel/e820.c +1 -1
@@ -567,7 +567,7 @@ void __init setup_memory_region(void)if (copy_e820_map (E820_MAP ,E820_MAP_NR ) <0 )early_panic ("Cannot find a valid memory map" );printk (KERN_INFO "BIOS-provided physical RAM map:\n" ); -e820_print_map ("BIOS-e820" ); +e820_print_map (MAP_TYPE_STR ); }static int __init parse_memopt (char *p)
include/asm-x86_64/e820.h +15 -0
@@ -55,7 +55,22 @@ extern void finish_e820_parsing(void);extern struct e820map e820; +#define EBDA_ADDR_POINTER 0x40E +static inline void native_ebda_info (unsigned *addr,unsigned *size) +{ + *addr = *(unsigned short *)EBDA_ADDR_POINTER ; + *addr <<=4 ; + *size = *(unsigned short *)(unsigned long )*addr; +} +extern unsigned ebda_addr, ebda_size; +#ifdef CONFIG_PARAVIRT +#include <asm/paravirt.h> +#else +#define ebda_info native_ebda_info +#define MAP_TYPE_STR "BIOS-e820" +#endif +#endif /*!__ASSEMBLY__*/ #endif /*__E820_HEADER*/
--
PATCH 10/17 paravirt_ops - boot changes
In reply to a message not in the archiveplain text document attachment (xx-paravirt-boot.patch) Boot up code modifications to get paravirt ops running.
arch/x86_64/kernel/head.S +61 -2
@@ -16,6 +16,13 @@ #include <asm/page.h> #include <asm/msr.h> #include <asm/cache.h> + +#ifdef CONFIG_PARAVIRT +#include <asm/asm-offsets.h> +#include <asm/paravirt.h> +#else +#define GET_CR2_INTO_RAX mov %cr2, %rax +#endif /* we are not able to switch in one step to the final KERNEL ADRESS SPACE * because we need identity-mapped pages on setup so define __START_KERNEL to
@@ -106,6 +113,14 @@ startup_64: * reload the page tables here. */ +#ifdef CONFIG_PARAVIRT + /* a CS ended in 0x3 indicates we're in userspace. That's where + * our paravirt guests run. */ + movq %cs, %rax + testq $0x3, %rax + jnz startup_paravirt +#endif + /* Enable PAE mode and PGE */ xorq %rax, %rax btsq $5, %rax
@@ -208,10 +223,11 @@ ENTRY(early_idt_handler) cmpl $2,early_recursion_flag(%rip) jz 1f incl early_recursion_flag(%rip) - xorl %eax,%eax movq 8(%rsp),%rsi # get rip movq (%rsp),%rdx - movq %cr2,%rcx + GET_CR2_INTO_RAX + movq %rax,%rcx + xorq %rax, %rax leaq early_idt_msg(%rip),%rdi call early_printk cmpl $2,early_recursion_flag(%rip)
@@ -232,6 +248,47 @@ early_idt_msg: early_idt_ripmsg: .asciz "RIP %s\n" +#ifdef CONFIG_PARAVIRT +ENTRY(startup_paravirt) + cld + + /* initial stack location */ + movq $(init_thread_union+THREAD_SIZE),%rsp + + /* We take pains to preserve all the regs. */ + pushq %r11 + pushq %r10 + pushq %r9 + pushq %r8 + pushq %rsi + pushq %rdi + pushq %rdx + pushq %rcx + pushq %rax + + /* paravirt.o is last in link, and that probe fn never returns */ + pushq $__start_paravirtprobe +1: + movq 0(%rsp), %rax + pushq (%rax) + movq 8(%rsp), %rdi + call *(%rsp) + popq %rax + + movq 0x10(%rsp), %rax + movq 0x18(%rsp), %rcx + movq 0x20(%rsp), %rdx + movq 0x28(%rsp), %rdi + movq 0x30(%rsp), %rsi + movq 0x38(%rsp), %r8 + movq 0x40(%rsp), %r9 + movq 0x48(%rsp), %r10 + movq 0x50(%rsp), %r11 + + addl $8, (%rsp) + jmp 1b +#endif + .code32 ENTRY(no_long_mode) /* This isn't an x86-64 CPU so hang */
@@ -317,7 +374,9 @@ ENTRY(wakeup_level4_pgt) #endif #ifndef CONFIG_HOTPLUG_CPU + #ifndef CONFIG_PARAVIRT __INITDATA + #endif #endif /* * This default setting generates an ident mapping at address 0x100000
arch/x86_64/kernel/head64.c +6 -2
@@ -10,6 +10,7 @@#include <linux/kernel.h> #include <linux/string.h> #include <linux/percpu.h> +#include <linux/module.h> #include <asm/processor.h> #include <asm/proto.h>
@@ -20,6 +21,9 @@#include <asm/pgtable.h> #include <asm/sections.h> +/* Virtualized guests may want to use it */ +EXPORT_SYMBOL (cpu_gdt_descr); +/* Don't add a printk in there. printk relies on the PDA which is not initialized yet. */ static void __init clear_bss (void )
@@ -62,7 +66,7 @@ void __init x86_64_start_kernel(char * rfor (i =0 ; i <IDT_ENTRIES ; i++)set_intr_gate (i, early_idt_handler); - asmvolatile ("lidt %0" ::"m" (idt_descr)); +load_idt ((const struct desc_ptr *)&idt_descr);early_printk ("Kernel alive\n" );
@@ -70,7 +74,7 @@ void __init x86_64_start_kernel(char * r* switch to init_level4_pgt from boot_level4_pgt */ memcpy (init_level4_pgt, boot_level4_pgt,PTRS_PER_PGD *sizeof (pgd_t)); - asmvolatile ("movq %0,%%cr3" ::"r" (__pa_symbol (&init_level4_pgt))); +write_cr3 (__pa_symbol (&init_level4_pgt));for (i =0 ; i <NR_CPUS ; i++)cpu_pda (i) = &boot_cpu_pda[i];
arch/x86_64/kernel/process.c +6 -5
@@ -42,6 +42,7 @@#include <asm/system.h> #include <asm/io.h> #include <asm/processor.h> +#include <asm/system.h> #include <asm/i387.h> #include <asm/mmu_context.h> #include <asm/pda.h>
@@ -338,10 +339,10 @@ void __show_regs(struct pt_regs * regs)rdmsrl (MSR_GS_BASE , gs);rdmsrl (MSR_KERNEL_GS_BASE , shadowgs); - asm("movq %%cr0, %0" :"=r" (cr0)); - asm("movq %%cr2, %0" :"=r" (cr2)); - asm("movq %%cr3, %0" :"=r" (cr3)); - asm("movq %%cr4, %0" :"=r" (cr4)); + cr0 =read_cr0 (); + cr2 =read_cr2 (); + cr3 =read_cr3 (); + cr4 =read_cr4 ();printk ("FS: %016lx(%04x) GS:%016lx(%04x) knlGS:%016lx\n" , fs,fsindex,gs,gsindex,shadowgs);
@@ -578,7 +579,7 @@ __switch_to(struct task_struct *prev_p,/* * Reload esp0, LDT and the page table pointer: */ - tss->rsp0 = next->rsp0; +load_rsp0 (tss, next);/* * Switch DS and ES.
arch/x86_64/kernel/reboot.c +2 -1
@@ -15,6 +15,7 @@#include <asm/pgtable.h> #include <asm/tlbflush.h> #include <asm/apic.h> +#include <asm/desc.h> /* * Power off function, if any
@@ -131,7 +132,7 @@ void machine_emergency_restart(void) }case BOOT_TRIPLE : - __asm__ __volatile__("lidt (%0)" : :"r" (&no_idt)); +load_idt ((const struct desc_ptr *)&no_idt); __asm__ __volatile__("int3" ); reboot_type =BOOT_KBD ;
arch/x86_64/kernel/setup.c +8 -6
@@ -327,10 +327,7 @@ static void discover_ebda(void)* there is a real-mode segmented pointer pointing to the * 4K EBDA area at 0x40E */ - ebda_addr = *(unsigned short *)EBDA_ADDR_POINTER ; - ebda_addr <<=4 ; - - ebda_size = *(unsigned short *)(unsigned long )ebda_addr; +ebda_info (&ebda_addr,&ebda_size);/* Round EBDA up to pages */ if (ebda_size ==0 )
@@ -341,6 +338,12 @@ static void discover_ebda(void) ebda_size =64 *1024 ; } +/* Overridden in paravirt.c if CONFIG_PARAVIRT */ +void __attribute__((weak))memory_setup (void ) +{ +return setup_memory_region (); +} +void __init setup_arch (char **cmdline_p) {printk (KERN_INFO "Command line: %s\n" , saved_command_line);
@@ -356,7 +359,7 @@ void __init setup_arch(char **cmdline_p) rd_prompt = ((RAMDISK_FLAGS &RAMDISK_PROMPT_FLAG ) !=0 ); rd_doload = ((RAMDISK_FLAGS &RAMDISK_LOAD_FLAG ) !=0 );#endif -setup_memory_region (); +memory_setup ();copy_edd ();if (!MOUNT_ROOT_RDONLY )
@@ -561,7 +564,6 @@ static int __cpuinit get_model_name(strureturn 1 ; } -static void __cpuinit display_cacheinfo (struct cpuinfo_x86 *c) {unsigned int n, dummy, eax, ebx, ecx, edx;
arch/x86_64/kernel/setup64.c +12 -5
@@ -123,7 +123,7 @@ void pda_init(int cpu) asmvolatile ("movl %0,%%fs ; movl %0,%%gs" ::"r" (0 ));/* Memory clobbers used to order PDA accessed */ mb (); -wrmsrl (MSR_GS_BASE , pda); +wrmsrl (MSR_GS_BASE , (u64 )pda);mb (); pda->cpunumber = cpu;
@@ -152,7 +152,7 @@ char boot_exception_stacks[(N_EXCEPTION_ __attribute__((section(".bss.page_aligned")));/* May not be marked __init: used by software suspend */ -void syscall_init (void ) +void x86_64_syscall_init (void ) {/* * LSTAR and STAR live in a bit strange symbiosis.
@@ -160,7 +160,7 @@ void syscall_init(void)* but only a 32bit target. LSTAR sets the 64bit rip. */ wrmsrl (MSR_STAR , ((u64 )__USER32_CS)<<48 | ((u64 )__KERNEL_CS)<<32 ); -wrmsrl (MSR_LSTAR , system_call); +wrmsrl (MSR_LSTAR , (u64 )system_call);#ifdef CONFIG_IA32_EMULATION syscall32_cpu_init ();
@@ -170,6 +170,12 @@ void syscall_init(void)wrmsrl (MSR_SYSCALL_MASK ,EF_TF |EF_DF |EF_IE |0x3000 ); } +/* Overriden in paravirt.c if CONFIG_PARAVIRT */ +void __attribute__((weak))syscall_init (void ) +{ +x86_64_syscall_init (); +} +void __cpuinit check_efer (void ) {unsigned long efer;
@@ -223,8 +229,8 @@ void __cpuinit cpu_init (void)memcpy (cpu_gdt (cpu), cpu_gdt_table,GDT_SIZE ); cpu_gdt_descr[cpu].size =GDT_SIZE ; - asmvolatile ("lgdt %0" ::"m" (cpu_gdt_descr[cpu])); - asmvolatile ("lidt %0" ::"m" (idt_descr)); +load_gdt ((const struct desc_ptr *)&cpu_gdt_descr[cpu]); +load_idt ((const struct desc_ptr *)&idt_descr);memset (me->thread.tls_array,0 ,GDT_ENTRY_TLS_ENTRIES *8 );syscall_init ();
@@ -267,6 +273,7 @@ void __cpuinit cpu_init (void)BUG ();enter_lazy_tlb (&init_mm, me); +load_rsp0 (t, ¤t->thread);set_tss_desc (cpu, t);load_TR_desc ();load_LDT (&init_mm.context);
arch/x86_64/kernel/smpboot.c +1 -1
@@ -848,7 +848,7 @@ do_rest: start_rip =setup_trampoline (); init_rsp = c_idle.idle->thread.rsp; -per_cpu (init_tss,cpu).rsp0 = init_rsp; +load_rsp0 (&per_cpu (init_tss,cpu), &c_idle.idle->thread); initial_code = start_secondary;clear_tsk_thread_flag (c_idle.idle,TIF_FORK );
arch/x86_64/kernel/vmlinux.lds.S +15 -2
@@ -61,6 +61,13 @@ SECTIONS CONSTRUCTORS } :data + .paravirtprobe : AT(ADDR(.paravirtprobe) - LOAD_OFFSET) { + __start_paravirtprobe = .; + *(.paravirtprobe); + *(.paravirtprobe_failsafe); + __stop_paravirtprobe = .; + } + _edata = .; /* End of data section */ . = ALIGN(PAGE_SIZE);
@@ -180,14 +187,20 @@ SECTIONS __con_initcall_end = .; SECURITY_INIT . = ALIGN(8); - __alt_instructions = .; .altinstructions : AT(ADDR(.altinstructions) - LOAD_OFFSET) { + __alt_instructions = .; *(.altinstructions) + __alt_instructions_end = .; } - __alt_instructions_end = .; .altinstr_replacement : AT(ADDR(.altinstr_replacement) - LOAD_OFFSET) { *(.altinstr_replacement) } + . = ALIGN(8); + .parainstructions : AT(ADDR(.parainstructions) - LOAD_OFFSET) { + __start_parainstructions = .; + *(.parainstructions) + __stop_parainstructions = .; + } /* .exit.text is discard at runtime, not link time, to deal with references from .altinstructions and .eh_frame */ .exit.text : AT(ADDR(.exit.text) - LOAD_OFFSET) { *(.exit.text) }
--
PATCH 11/17 paravirt_ops - asm-offset updates
In reply to a message not in the archiveplain text document attachment (xx-paravirt-asm-offsets.patch) Add offsets for use of paravirt-ops in assembly.
arch/x86_64/kernel/asm-offsets.c +15 -0
@@ -15,6 +15,9 @@#include <asm/segment.h> #include <asm/thread_info.h> #include <asm/ia32.h> +#ifdef CONFIG_PARAVIRT +#include <asm/paravirt.h> +#endif #define DEFINE (sym, val) \ asm volatile("\n->" #sym " %0 " #val : : "i" (val))
@@ -71,5 +74,17 @@ int main(void)DEFINE (TSS_ist, offsetof(struct tss_struct , ist));BLANK ();DEFINE (crypto_tfm_ctx_offset, offsetof(struct crypto_tfm , __crt_ctx)); + +#ifdef CONFIG_PARAVIRT +#define ENTRY (entry) DEFINE(PARAVIRT_ ## entry, offsetof(struct paravirt_ops, entry)) +BLANK (); +ENTRY (paravirt_enabled); +ENTRY (irq_disable); +ENTRY (irq_enable); +ENTRY (sysret); +ENTRY (iret); +ENTRY (read_cr2); +ENTRY (swapgs); +#endif return 0 ; }
--
PATCH 12/17 paravirt_ops - interrupt/exception changes
In reply to a message not in the archiveplain text document attachment (xx-paravirt-irqs.patch) Interrupt updates for paravirt ops.
arch/x86_64/ia32/ia32entry.S +13 -6
@@ -16,6 +16,13 @@ #include <asm/irqflags.h> #include <linux/linkage.h> +#ifdef CONFIG_PARAVIRT +#include <asm/paravirt.h> +#else +#define ENABLE_INTERRUPTS(CLBR) sti +#define DISABLE_INTERRUPTS(CLBR) cli +#endif + #define IA32_NR_syscalls ((ia32_syscall_end - ia32_sys_call_table)/8) .macro IA32_ARG_FIXUP noebp=0
@@ -81,7 +88,7 @@ ENTRY(ia32_sysenter_target) * No need to follow this irqs on/off section: the syscall * disabled irqs, here we enable it straight after entry: */ - sti + ENABLE_INTERRUPTS(CLBR_NONE) movl %ebp,%ebp /* zero extension */ pushq $__USER32_DS CFI_ADJUST_CFA_OFFSET 8
@@ -123,7 +130,7 @@ sysenter_do_call: call *ia32_sys_call_table(,%rax,8) movq %rax,RAX-ARGOFFSET(%rsp) GET_THREAD_INFO(%r10) - cli + DISABLE_INTERRUPTS(CLBR_NONE) TRACE_IRQS_OFF testl $_TIF_ALLWORK_MASK,threadinfo_flags(%r10) jnz int_ret_from_sys_call
@@ -141,7 +148,7 @@ sysenter_do_call: CFI_REGISTER rip,rdx TRACE_IRQS_ON swapgs - sti /* sti only takes effect after the next instruction */ + ENABLE_INTERRUPTS(CLBR_NONE) /* sti only takes effect after the next instruction */ /* sysexit */ .byte 0xf, 0x35
@@ -199,7 +206,7 @@ ENTRY(ia32_cstar_target) * No need to follow this irqs on/off section: the syscall * disabled irqs and here we enable it straight after entry: */ - sti + ENABLE_INTERRUPTS(CLBR_NONE) SAVE_ARGS 8,1,1 movl %eax,%eax /* zero extension */ movq %rax,ORIG_RAX-ARGOFFSET(%rsp)
@@ -232,7 +239,7 @@ cstar_do_call: call *ia32_sys_call_table(,%rax,8) movq %rax,RAX-ARGOFFSET(%rsp) GET_THREAD_INFO(%r10) - cli + DISABLE_INTERRUPTS(CLBR_NONE) TRACE_IRQS_OFF testl $_TIF_ALLWORK_MASK,threadinfo_flags(%r10) jnz int_ret_from_sys_call
@@ -307,7 +314,7 @@ ENTRY(ia32_syscall) * No need to follow this irqs on/off section: the syscall * disabled irqs and here we enable it straight after entry: */ - sti + ENABLE_INTERRUPTS(CLBR_NONE) movl %eax,%eax pushq %rax CFI_ADJUST_CFA_OFFSET 8
arch/x86_64/kernel/entry.S +63 -39
302 lines not on this page · raw message
arch/x86_64/kernel/i8259.c +5 -2
@@ -77,7 +77,7 @@ BUILD_16_IRQS(0xc) BUILD_16_IRQS(0xd) BUIRQ (x,c),IRQ (x,d),IRQ (x,e),IRQ (x,f) /* for the irq vectors */ -static void (*interrupt[NR_VECTORS -FIRST_EXTERNAL_VECTOR ])(void ) = { +void (*interrupt[NR_VECTORS -FIRST_EXTERNAL_VECTOR ])(void ) = {IRQLIST_16 (0x2 ),IRQLIST_16 (0x3 ),IRQLIST_16 (0x4 ),IRQLIST_16 (0x5 ),IRQLIST_16 (0x6 ),IRQLIST_16 (0x7 ),IRQLIST_16 (0x8 ),IRQLIST_16 (0x9 ),IRQLIST_16 (0xa ),IRQLIST_16 (0xb ),
@@ -501,7 +501,10 @@ static int __init init_timer_sysfs(void)device_initcall (init_timer_sysfs); -void __init init_IRQ (void ) +/* Overridden in paravirt.c */ +void init_IRQ (void ) __attribute__((weak,alias ("native_init_IRQ" ))); + +void __init native_init_IRQ (void ) {int i;
arch/x86_64/kernel/traps.c +1 -0
@@ -1067,6 +1067,7 @@ asmlinkage void math_state_restore(void)task_thread_info (me)->status |=TS_USEDFPU ; me->fpu_counter++; } +EXPORT_SYMBOL_GPL (math_state_restore);void __init trap_init (void ) {
include/asm-x86_64/irq.h +3 -0
@@ -46,6 +46,9 @@ static __inline__ int irq_canonicalize(iextern void fixup_irqs (cpumask_t map);#endif +void init_IRQ (void ); +void native_init_IRQ (void ); +#define __ARCH_HAS_DO_SOFTIRQ 1#endif /* _ASM_IRQ_H */
include/asm-x86_64/irqflags.h +15 -4
@@ -11,6 +11,15 @@#define _ASM_IRQFLAGS_H#ifndef __ASSEMBLY__ +#ifdef CONFIG_PARAVIRT +#include <asm/paravirt.h> + +static inline int raw_irqs_disabled_flags (unsigned long flags) +{ +return !(flags & (1 <<9 )); +} +#else +/* * Interrupt control: */
@@ -30,8 +39,6 @@ static inline unsigned long __raw_local_return flags; } -#define raw_local_save_flags (flags) \ - do { (flags) = __raw_local_save_flags(); } while (0)static inline void raw_local_irq_restore (unsigned long flags) {
@@ -100,8 +107,6 @@ static inline unsigned long __raw_local_return flags; } -#define raw_local_irq_save (flags) \ - do { (flags) = __raw_local_irq_save(); } while (0)static inline int raw_irqs_disabled (void ) {
@@ -128,6 +133,7 @@ static inline void halt(void) __asm__ __volatile__("hlt": : :"memory"); } +#endif /* CONFIG_PARAVIRT */ #else /* __ASSEMBLY__: */ # ifdef CONFIG_TRACE_IRQFLAGS # define TRACE_IRQS_ON call trace_hardirqs_on_thunk
@@ -138,4 +144,9 @@ static inline void halt(void)# endif #endif +#define raw_local_save_flags (flags) \ + do { (flags) = __raw_local_save_flags(); } while (0) + +#define raw_local_irq_save (flags) \ + do { (flags) = __raw_local_irq_save(); } while (0)#endif
--
PATCH 13/17 paravirt_ops - time updates
In reply to a message not in the archiveplain text document attachment (xx-paravirt-time.patch) General time changes for paravirt_ops.
include/asm-x86_64/time.h new file +18 -0
@@ -0,0 +1,18 @@ +#ifndef _ASM_X86_64_TIME_H +#define _ASM_X86_64_TIME_H + +inline void time_init_hook (void ); +unsigned long do_get_cmos_time (void ); +void do_set_rtc_mmss (unsigned long nowtime); + +#ifdef CONFIG_PARAVIRT +#include <asm/paravirt.h> +#else /* !CONFIG_PARAVIRT */ + +#define get_wallclock () do_get_cmos_time() +#define set_wallclock (x) do_set_rtc_mmss(x) +#define do_time_init () time_init_hook() + +#endif /* CONFIG_PARAVIRT */ + +#endif
arch/x86_64/kernel/time.c +28 -13
99 lines not on this page · raw message
include/asm-x86_64/timex.h +17 -2
@@ -31,14 +31,29 @@ static __always_inline cycles_t get_cycl {unsigned long long ret;unsigned eax; +unsigned int (*fn)(unsigned int ) = &cpuid_eax;/* Don't do an additional sync on CPUs where we know RDTSC is already synchronous. */ -alternative_io ("cpuid" ,ASM_NOP2 ,X86_FEATURE_SYNC_RDTSC , - "=a" (eax), "0" (1) : "ebx","ecx","edx","memory"); +alternative_io ("call *%3" ,ASM_NOP2 ,X86_FEATURE_SYNC_RDTSC , +"=a" (eax) ,"D" (1 ) ,"m" (fn));rdtscll (ret);return ret; } +/* Inside a vsyscall, we cannot call paravirt functions. (like rdtsc +* and cpuid). For the host, use this function instead */ +static __always_inline cycles_t vget_cycles_sync(void) +{ +unsigned long ret; +unsigned eax; +/* Don't do an additional sync on CPUs where we know +RDTSC is already synchronous. */ +alternative_io ("cpuid" ,ASM_NOP2 ,X86_FEATURE_SYNC_RDTSC , + "=a" (eax), "0" (1) : "ebx","ecx","edx","memory"); + + asmvolatile ("rdtsc" :"=A" (ret)); +return ret; +}extern unsigned int cpu_khz;extern int read_current_timer (unsigned long *timer_value);
--
PATCH 14/17 paravirt_ops - vsyscall
In reply to a message not in the archiveplain text document attachment (xx-paravirt-vsyscall.patch) vsyscall interface updates for paravirt ops.
arch/x86_64/kernel/vsyscall.c +22 -6
@@ -73,7 +73,7 @@ static __always_inline void do_vgettimeo usec = __xtime.tv_nsec /1000 ;if (__vxtime.mode !=VXTIME_HPET ) { - t =get_cycles_sync (); + t =vget_cycles_sync ();if (t < __vxtime.last_tsc) t = __vxtime.last_tsc; usec += ((t - __vxtime.last_tsc) *
@@ -147,8 +147,8 @@ time_t __vsyscall(1) vtime(time_t *t) long __vsyscall(2) vgetcpu(unsigned *cpu, unsigned *node, struct getcpu_cache *tcache) { -unsigned int dummy, p; -unsigned long j =0 ; +unsigned int p; +unsigned long dummy, j =0 ;/* Fast cache - only recompute value once per jiffies and avoid relatively costly rdtscp/cpuid otherwise.
@@ -162,7 +162,8 @@ vgetcpu(unsigned *cpu, unsigned *node, s p = tcache->blob[1 ]; }else if (__vgetcpu_mode ==VGETCPU_RDTSCP ) {/* Load per CPU data from RDTSCP */ -rdtscp (dummy, dummy, p); +/* rdtscp() cannot be called due to the paravirt indirection */ + asm("rdtscp" :"=A" (dummy),"=c" (p)); }else {/* Load per CPU data from GDT */ asm("lsl %1,%0" :"=r" (p) :"r" (__PER_CPU_SEG));
@@ -256,7 +257,11 @@ static void __cpuinit vsyscall_set_cpu(i node = cpu_to_node[cpu];#endif if (cpu_has (&cpu_data[cpu],X86_FEATURE_RDTSCP )) -write_rdtscp_aux ((node <<12 ) | cpu); +/* This is write_rdtscp_aux. It cannot be called directly +* due to the paravirt indirection */ + asm("wrmsr" :/* no output */ + :"d" (0 ), +"a" ((node <<12 ) | cpu),"c" (0xc0000103 ));/* Store cpu number in limit so that it can be loaded quickly in user space in vgetcpu.
@@ -285,8 +290,12 @@ cpu_vsyscall_notifier(struct notifier_blstatic void __init map_vsyscall (void ) { +#ifndef CONFIG_PARAVIRT extern char __vsyscall_0;unsigned long physaddr_page0 =__pa_symbol (&__vsyscall_0); +#else +unsigned long physaddr_page0 =__pa_symbol (paravirt_ops.vsyscall_page); +#endif /* Note that VSYSCALL_MAPPED_PAGES must agree with the code below. */ __set_fixmap (VSYSCALL_FIRST_PAGE , physaddr_page0,PAGE_KERNEL_VSYSCALL );
@@ -299,7 +308,14 @@ static int __init vsyscall_init(void)BUG_ON ((unsigned long ) &vtime !=VSYSCALL_ADDR (__NR_vtime));BUG_ON ((VSYSCALL_ADDR (0 ) !=__fix_to_virt (VSYSCALL_FIRST_PAGE )));BUG_ON ((unsigned long ) &vgetcpu !=VSYSCALL_ADDR (__NR_vgetcpu)); -map_vsyscall (); +#ifdef CONFIG_PARAVIRT + if (paravirt_ops.vsyscall_page) +#endif +map_vsyscall (); +#ifdef CONFIG_PARAVIRT + else + __sysctl_vsyscall =0 ; +#endif #ifdef CONFIG_SYSCTL register_sysctl_table (kernel_root_table2,0 );#endif
--
PATCH 15/17 paravirt_op - kconfig
In reply to a message not in the archiveplain text document attachment (xx-paravirt-kconfig.patch) Add the config options for paravirt_ops and x86_64
arch/x86_64/Kconfig.debug +11 -0
@@ -55,6 +55,17 @@ config DEBUG_STACK_USAGE This option will slow down process creation somewhat. +config DEBUG_PARAVIRT + bool "Enable some paravirtualization debugging" + default y + depends on PARAVIRT && DEBUG_KERNEL + help + Currently deliberately clobbers regs which are allowed to be + clobbered in inlined paravirt hooks, even in native mode. + If turning this off solves a problem, then DISABLE_INTERRUPTS() or + ENABLE_INTERRUPTS() is lying about what registers can be clobbered. + + #config X86_REMOTE_DEBUG # bool "kgdb debugging stub"
arch/x86_64/Kconfig +12 -0
@@ -349,6 +349,18 @@ config NODES_SHIFT # Dummy CONFIG option to select ACPI_NUMA from drivers/acpi/Kconfig. +config PARAVIRT + bool "Paravirtualization support (EXPERIMENTAL)" + depends on EXPERIMENTAL + help + Paravirtualization is a way of running multiple instances of + Linux on the same machine, under a hypervisor. This option + changes the kernel so it can modify itself when it is run + under a hypervisor, improving performance significantly. + However, when run without a hypervisor the kernel is + theoretically slower. If in doubt, say N. + + config X86_64_ACPI_NUMA bool "ACPI NUMA detection" depends on NUMA
--
PATCH 16/17 paravirt_ops - touch ups
In reply to a message not in the archiveplain text document attachment (xx-paravirt-touchups.patch) Some miscellaneous clean ups.
arch/x86_64/ia32/syscall32.c +1 -1
@@ -119,5 +119,5 @@ void syscall32_cpu_init(void)checking_wrmsrl (MSR_IA32_SYSENTER_ESP ,0ULL );checking_wrmsrl (MSR_IA32_SYSENTER_EIP , (u64 )ia32_sysenter_target); -wrmsrl (MSR_CSTAR , ia32_cstar_target); +wrmsrl (MSR_CSTAR , (u64 )ia32_cstar_target); }
arch/x86_64/mm/pageattr.c +1 -1
@@ -81,7 +81,7 @@ static void flush_kernel_map(void *arg)void *adr =page_address (pg);if (cpu_has_clflush)cache_flush_page (adr); -__flush_tlb_one (adr); +__flush_tlb_one ((u64 )adr); } }
include/linux/irqflags.h +5 -5
@@ -74,11 +74,11 @@#endif /* CONFIG_TRACE_IRQFLAGS_SUPPORT */ #ifdef CONFIG_TRACE_IRQFLAGS_SUPPORT -static inline void safe_halt (void ) -{ -trace_hardirqs_on (); -raw_safe_halt (); -} +#define safe_halt () \ + do { \ + trace_hardirqs_on(); \ + raw_safe_halt(); \ + } while (0)#define local_save_flags (flags) raw_local_save_flags(flags)
--
PATCH 17/17 paravirt_ops - pda entry
In reply to a message not in the archiveplain text document attachment (xx-paravirt-pda.patch) We don't actually use this. But we started to. This patch adds a vcpu entry into the PDA. This can come in handy, but we are not sure if we want it. This is why it's in its own little patch.
arch/x86_64/kernel/asm-offsets.c +3 -0
@@ -48,6 +48,9 @@ int main(void)ENTRY (cpunumber);ENTRY (irqstackptr);ENTRY (data_offset); +/* XXX: this should probably be a paravirt_ops stub, to be filled in +* with the hypervisor code */ +ENTRY (vcpu);BLANK ();#undef ENTRY#ifdef CONFIG_IA32_EMULATION
include/asm-x86_64/pda.h +1 -0
@@ -29,6 +29,7 @@ struct x8664_pda {short isidle;struct mm_struct *active_mm;unsigned apic_timer_irqs; +void *vcpu; }____cacheline_aligned_in_smp ;extern struct x8664_pda *_cpu_pda[];
--