mirror of
https://github.com/adulau/aha.git
synced 2025-01-03 22:53:18 +00:00
Merge branch 'x86/fixmap' into x86/devel
Conflicts: arch/x86/mm/init_64.c Signed-off-by: Ingo Molnar <mingo@elte.hu>
This commit is contained in:
commit
6236af82d8
10 changed files with 130 additions and 112 deletions
|
@ -420,6 +420,8 @@ struct pv_mmu_ops pv_mmu_ops = {
|
||||||
.enter = paravirt_nop,
|
.enter = paravirt_nop,
|
||||||
.leave = paravirt_nop,
|
.leave = paravirt_nop,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
.set_fixmap = native_set_fixmap,
|
||||||
};
|
};
|
||||||
|
|
||||||
EXPORT_SYMBOL_GPL(pv_time_ops);
|
EXPORT_SYMBOL_GPL(pv_time_ops);
|
||||||
|
|
|
@ -148,15 +148,15 @@ static __init void *spp_getpage(void)
|
||||||
return ptr;
|
return ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
static __init void
|
void
|
||||||
set_pte_phys(unsigned long vaddr, unsigned long phys, pgprot_t prot)
|
set_pte_vaddr(unsigned long vaddr, pte_t new_pte)
|
||||||
{
|
{
|
||||||
pgd_t *pgd;
|
pgd_t *pgd;
|
||||||
pud_t *pud;
|
pud_t *pud;
|
||||||
pmd_t *pmd;
|
pmd_t *pmd;
|
||||||
pte_t *pte, new_pte;
|
pte_t *pte;
|
||||||
|
|
||||||
pr_debug("set_pte_phys %lx to %lx\n", vaddr, phys);
|
pr_debug("set_pte_vaddr %lx to %lx\n", vaddr, native_pte_val(new_pte));
|
||||||
|
|
||||||
pgd = pgd_offset_k(vaddr);
|
pgd = pgd_offset_k(vaddr);
|
||||||
if (pgd_none(*pgd)) {
|
if (pgd_none(*pgd)) {
|
||||||
|
@ -183,7 +183,6 @@ set_pte_phys(unsigned long vaddr, unsigned long phys, pgprot_t prot)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
new_pte = pfn_pte(phys >> PAGE_SHIFT, prot);
|
|
||||||
|
|
||||||
pte = pte_offset_kernel(pmd, vaddr);
|
pte = pte_offset_kernel(pmd, vaddr);
|
||||||
if (!pte_none(*pte) && pte_val(new_pte) &&
|
if (!pte_none(*pte) && pte_val(new_pte) &&
|
||||||
|
@ -226,18 +225,6 @@ void __init cleanup_highmap(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* NOTE: this is meant to be run only at boot */
|
|
||||||
void __init __set_fixmap(enum fixed_addresses idx, unsigned long phys, pgprot_t prot)
|
|
||||||
{
|
|
||||||
unsigned long address = __fix_to_virt(idx);
|
|
||||||
|
|
||||||
if (idx >= __end_of_fixed_addresses) {
|
|
||||||
printk(KERN_ERR "Invalid __set_fixmap\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
set_pte_phys(address, phys, prot);
|
|
||||||
}
|
|
||||||
|
|
||||||
static unsigned long __initdata table_start;
|
static unsigned long __initdata table_start;
|
||||||
static unsigned long __meminitdata table_end;
|
static unsigned long __meminitdata table_end;
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#include <asm/pgalloc.h>
|
#include <asm/pgalloc.h>
|
||||||
#include <asm/pgtable.h>
|
#include <asm/pgtable.h>
|
||||||
#include <asm/tlb.h>
|
#include <asm/tlb.h>
|
||||||
|
#include <asm/fixmap.h>
|
||||||
|
|
||||||
pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address)
|
pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address)
|
||||||
{
|
{
|
||||||
|
@ -274,3 +275,22 @@ int ptep_clear_flush_young(struct vm_area_struct *vma,
|
||||||
|
|
||||||
return young;
|
return young;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int fixmaps_set;
|
||||||
|
|
||||||
|
void __native_set_fixmap(enum fixed_addresses idx, pte_t pte)
|
||||||
|
{
|
||||||
|
unsigned long address = __fix_to_virt(idx);
|
||||||
|
|
||||||
|
if (idx >= __end_of_fixed_addresses) {
|
||||||
|
BUG();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
set_pte_vaddr(address, pte);
|
||||||
|
fixmaps_set++;
|
||||||
|
}
|
||||||
|
|
||||||
|
void native_set_fixmap(enum fixed_addresses idx, unsigned long phys, pgprot_t flags)
|
||||||
|
{
|
||||||
|
__native_set_fixmap(idx, pfn_pte(phys >> PAGE_SHIFT, flags));
|
||||||
|
}
|
||||||
|
|
|
@ -71,7 +71,7 @@ void show_mem(void)
|
||||||
* Associate a virtual page frame with a given physical page frame
|
* Associate a virtual page frame with a given physical page frame
|
||||||
* and protection flags for that frame.
|
* and protection flags for that frame.
|
||||||
*/
|
*/
|
||||||
static void set_pte_pfn(unsigned long vaddr, unsigned long pfn, pgprot_t flags)
|
void set_pte_vaddr(unsigned long vaddr, pte_t pteval)
|
||||||
{
|
{
|
||||||
pgd_t *pgd;
|
pgd_t *pgd;
|
||||||
pud_t *pud;
|
pud_t *pud;
|
||||||
|
@ -94,8 +94,8 @@ static void set_pte_pfn(unsigned long vaddr, unsigned long pfn, pgprot_t flags)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
pte = pte_offset_kernel(pmd, vaddr);
|
pte = pte_offset_kernel(pmd, vaddr);
|
||||||
if (pgprot_val(flags))
|
if (pte_val(pteval))
|
||||||
set_pte_present(&init_mm, vaddr, pte, pfn_pte(pfn, flags));
|
set_pte_present(&init_mm, vaddr, pte, pteval);
|
||||||
else
|
else
|
||||||
pte_clear(&init_mm, vaddr, pte);
|
pte_clear(&init_mm, vaddr, pte);
|
||||||
|
|
||||||
|
@ -145,18 +145,6 @@ static int fixmaps;
|
||||||
unsigned long __FIXADDR_TOP = 0xfffff000;
|
unsigned long __FIXADDR_TOP = 0xfffff000;
|
||||||
EXPORT_SYMBOL(__FIXADDR_TOP);
|
EXPORT_SYMBOL(__FIXADDR_TOP);
|
||||||
|
|
||||||
void __set_fixmap (enum fixed_addresses idx, unsigned long phys, pgprot_t flags)
|
|
||||||
{
|
|
||||||
unsigned long address = __fix_to_virt(idx);
|
|
||||||
|
|
||||||
if (idx >= __end_of_fixed_addresses) {
|
|
||||||
BUG();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
set_pte_pfn(address, phys >> PAGE_SHIFT, flags);
|
|
||||||
fixmaps++;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* reserve_top_address - reserves a hole in the top of kernel address space
|
* reserve_top_address - reserves a hole in the top of kernel address space
|
||||||
* @reserve - size of hole to reserve
|
* @reserve - size of hole to reserve
|
||||||
|
@ -166,7 +154,7 @@ void __set_fixmap (enum fixed_addresses idx, unsigned long phys, pgprot_t flags)
|
||||||
*/
|
*/
|
||||||
void reserve_top_address(unsigned long reserve)
|
void reserve_top_address(unsigned long reserve)
|
||||||
{
|
{
|
||||||
BUG_ON(fixmaps > 0);
|
BUG_ON(fixmaps_set > 0);
|
||||||
printk(KERN_INFO "Reserving virtual address space above 0x%08x\n",
|
printk(KERN_INFO "Reserving virtual address space above 0x%08x\n",
|
||||||
(int)-reserve);
|
(int)-reserve);
|
||||||
__FIXADDR_TOP = -reserve - PAGE_SIZE;
|
__FIXADDR_TOP = -reserve - PAGE_SIZE;
|
||||||
|
|
|
@ -1013,6 +1013,33 @@ static unsigned xen_patch(u8 type, u16 clobbers, void *insnbuf,
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void xen_set_fixmap(unsigned idx, unsigned long phys, pgprot_t prot)
|
||||||
|
{
|
||||||
|
pte_t pte;
|
||||||
|
|
||||||
|
phys >>= PAGE_SHIFT;
|
||||||
|
|
||||||
|
switch (idx) {
|
||||||
|
case FIX_BTMAP_END ... FIX_BTMAP_BEGIN:
|
||||||
|
#ifdef CONFIG_X86_F00F_BUG
|
||||||
|
case FIX_F00F_IDT:
|
||||||
|
#endif
|
||||||
|
case FIX_WP_TEST:
|
||||||
|
case FIX_VDSO:
|
||||||
|
#ifdef CONFIG_X86_LOCAL_APIC
|
||||||
|
case FIX_APIC_BASE: /* maps dummy local APIC */
|
||||||
|
#endif
|
||||||
|
pte = pfn_pte(phys, prot);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
pte = mfn_pte(phys, prot);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
__native_set_fixmap(idx, pte);
|
||||||
|
}
|
||||||
|
|
||||||
static const struct pv_info xen_info __initdata = {
|
static const struct pv_info xen_info __initdata = {
|
||||||
.paravirt_enabled = 1,
|
.paravirt_enabled = 1,
|
||||||
.shared_kernel_pmd = 0,
|
.shared_kernel_pmd = 0,
|
||||||
|
@ -1167,6 +1194,8 @@ static const struct pv_mmu_ops xen_mmu_ops __initdata = {
|
||||||
.enter = paravirt_enter_lazy_mmu,
|
.enter = paravirt_enter_lazy_mmu,
|
||||||
.leave = xen_leave_lazy,
|
.leave = xen_leave_lazy,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
.set_fixmap = xen_set_fixmap,
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef CONFIG_SMP
|
#ifdef CONFIG_SMP
|
||||||
|
|
|
@ -7,7 +7,62 @@
|
||||||
# include "fixmap_64.h"
|
# include "fixmap_64.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
extern int fixmaps_set;
|
||||||
|
|
||||||
|
void __native_set_fixmap(enum fixed_addresses idx, pte_t pte);
|
||||||
|
void native_set_fixmap(enum fixed_addresses idx,
|
||||||
|
unsigned long phys, pgprot_t flags);
|
||||||
|
|
||||||
|
#ifndef CONFIG_PARAVIRT
|
||||||
|
static inline void __set_fixmap(enum fixed_addresses idx,
|
||||||
|
unsigned long phys, pgprot_t flags)
|
||||||
|
{
|
||||||
|
native_set_fixmap(idx, phys, flags);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define set_fixmap(idx, phys) \
|
||||||
|
__set_fixmap(idx, phys, PAGE_KERNEL)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Some hardware wants to get fixmapped without caching.
|
||||||
|
*/
|
||||||
|
#define set_fixmap_nocache(idx, phys) \
|
||||||
|
__set_fixmap(idx, phys, PAGE_KERNEL_NOCACHE)
|
||||||
|
|
||||||
#define clear_fixmap(idx) \
|
#define clear_fixmap(idx) \
|
||||||
__set_fixmap(idx, 0, __pgprot(0))
|
__set_fixmap(idx, 0, __pgprot(0))
|
||||||
|
|
||||||
|
#define __fix_to_virt(x) (FIXADDR_TOP - ((x) << PAGE_SHIFT))
|
||||||
|
#define __virt_to_fix(x) ((FIXADDR_TOP - ((x)&PAGE_MASK)) >> PAGE_SHIFT)
|
||||||
|
|
||||||
|
extern void __this_fixmap_does_not_exist(void);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 'index to address' translation. If anyone tries to use the idx
|
||||||
|
* directly without translation, we catch the bug with a NULL-deference
|
||||||
|
* kernel oops. Illegal ranges of incoming indices are caught too.
|
||||||
|
*/
|
||||||
|
static __always_inline unsigned long fix_to_virt(const unsigned int idx)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* this branch gets completely eliminated after inlining,
|
||||||
|
* except when someone tries to use fixaddr indices in an
|
||||||
|
* illegal way. (such as mixing up address types or using
|
||||||
|
* out-of-range indices).
|
||||||
|
*
|
||||||
|
* If it doesn't get removed, the linker will complain
|
||||||
|
* loudly with a reasonably clear error message..
|
||||||
|
*/
|
||||||
|
if (idx >= __end_of_fixed_addresses)
|
||||||
|
__this_fixmap_does_not_exist();
|
||||||
|
|
||||||
|
return __fix_to_virt(idx);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline unsigned long virt_to_fix(const unsigned long vaddr)
|
||||||
|
{
|
||||||
|
BUG_ON(vaddr >= FIXADDR_TOP || vaddr < FIXADDR_START);
|
||||||
|
return __virt_to_fix(vaddr);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -109,17 +109,8 @@ enum fixed_addresses {
|
||||||
__end_of_fixed_addresses
|
__end_of_fixed_addresses
|
||||||
};
|
};
|
||||||
|
|
||||||
extern void __set_fixmap(enum fixed_addresses idx,
|
|
||||||
unsigned long phys, pgprot_t flags);
|
|
||||||
extern void reserve_top_address(unsigned long reserve);
|
extern void reserve_top_address(unsigned long reserve);
|
||||||
|
|
||||||
#define set_fixmap(idx, phys) \
|
|
||||||
__set_fixmap(idx, phys, PAGE_KERNEL)
|
|
||||||
/*
|
|
||||||
* Some hardware wants to get fixmapped without caching.
|
|
||||||
*/
|
|
||||||
#define set_fixmap_nocache(idx, phys) \
|
|
||||||
__set_fixmap(idx, phys, PAGE_KERNEL_NOCACHE)
|
|
||||||
|
|
||||||
#define FIXADDR_TOP ((unsigned long)__FIXADDR_TOP)
|
#define FIXADDR_TOP ((unsigned long)__FIXADDR_TOP)
|
||||||
|
|
||||||
|
@ -128,38 +119,5 @@ extern void reserve_top_address(unsigned long reserve);
|
||||||
#define FIXADDR_START (FIXADDR_TOP - __FIXADDR_SIZE)
|
#define FIXADDR_START (FIXADDR_TOP - __FIXADDR_SIZE)
|
||||||
#define FIXADDR_BOOT_START (FIXADDR_TOP - __FIXADDR_BOOT_SIZE)
|
#define FIXADDR_BOOT_START (FIXADDR_TOP - __FIXADDR_BOOT_SIZE)
|
||||||
|
|
||||||
#define __fix_to_virt(x) (FIXADDR_TOP - ((x) << PAGE_SHIFT))
|
|
||||||
#define __virt_to_fix(x) ((FIXADDR_TOP - ((x)&PAGE_MASK)) >> PAGE_SHIFT)
|
|
||||||
|
|
||||||
extern void __this_fixmap_does_not_exist(void);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 'index to address' translation. If anyone tries to use the idx
|
|
||||||
* directly without tranlation, we catch the bug with a NULL-deference
|
|
||||||
* kernel oops. Illegal ranges of incoming indices are caught too.
|
|
||||||
*/
|
|
||||||
static __always_inline unsigned long fix_to_virt(const unsigned int idx)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* this branch gets completely eliminated after inlining,
|
|
||||||
* except when someone tries to use fixaddr indices in an
|
|
||||||
* illegal way. (such as mixing up address types or using
|
|
||||||
* out-of-range indices).
|
|
||||||
*
|
|
||||||
* If it doesn't get removed, the linker will complain
|
|
||||||
* loudly with a reasonably clear error message..
|
|
||||||
*/
|
|
||||||
if (idx >= __end_of_fixed_addresses)
|
|
||||||
__this_fixmap_does_not_exist();
|
|
||||||
|
|
||||||
return __fix_to_virt(idx);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline unsigned long virt_to_fix(const unsigned long vaddr)
|
|
||||||
{
|
|
||||||
BUG_ON(vaddr >= FIXADDR_TOP || vaddr < FIXADDR_START);
|
|
||||||
return __virt_to_fix(vaddr);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* !__ASSEMBLY__ */
|
#endif /* !__ASSEMBLY__ */
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -52,17 +52,6 @@ enum fixed_addresses {
|
||||||
__end_of_fixed_addresses
|
__end_of_fixed_addresses
|
||||||
};
|
};
|
||||||
|
|
||||||
extern void __set_fixmap(enum fixed_addresses idx,
|
|
||||||
unsigned long phys, pgprot_t flags);
|
|
||||||
|
|
||||||
#define set_fixmap(idx, phys) \
|
|
||||||
__set_fixmap(idx, phys, PAGE_KERNEL)
|
|
||||||
/*
|
|
||||||
* Some hardware wants to get fixmapped without caching.
|
|
||||||
*/
|
|
||||||
#define set_fixmap_nocache(idx, phys) \
|
|
||||||
__set_fixmap(idx, phys, PAGE_KERNEL_NOCACHE)
|
|
||||||
|
|
||||||
#define FIXADDR_TOP (VSYSCALL_END-PAGE_SIZE)
|
#define FIXADDR_TOP (VSYSCALL_END-PAGE_SIZE)
|
||||||
#define FIXADDR_SIZE (__end_of_fixed_addresses << PAGE_SHIFT)
|
#define FIXADDR_SIZE (__end_of_fixed_addresses << PAGE_SHIFT)
|
||||||
#define FIXADDR_START (FIXADDR_TOP - FIXADDR_SIZE)
|
#define FIXADDR_START (FIXADDR_TOP - FIXADDR_SIZE)
|
||||||
|
@ -71,30 +60,4 @@ extern void __set_fixmap(enum fixed_addresses idx,
|
||||||
#define FIXADDR_USER_START ((unsigned long)VSYSCALL32_VSYSCALL)
|
#define FIXADDR_USER_START ((unsigned long)VSYSCALL32_VSYSCALL)
|
||||||
#define FIXADDR_USER_END (FIXADDR_USER_START + PAGE_SIZE)
|
#define FIXADDR_USER_END (FIXADDR_USER_START + PAGE_SIZE)
|
||||||
|
|
||||||
#define __fix_to_virt(x) (FIXADDR_TOP - ((x) << PAGE_SHIFT))
|
|
||||||
|
|
||||||
extern void __this_fixmap_does_not_exist(void);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 'index to address' translation. If anyone tries to use the idx
|
|
||||||
* directly without translation, we catch the bug with a NULL-deference
|
|
||||||
* kernel oops. Illegal ranges of incoming indices are caught too.
|
|
||||||
*/
|
|
||||||
static __always_inline unsigned long fix_to_virt(const unsigned int idx)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* this branch gets completely eliminated after inlining,
|
|
||||||
* except when someone tries to use fixaddr indices in an
|
|
||||||
* illegal way. (such as mixing up address types or using
|
|
||||||
* out-of-range indices).
|
|
||||||
*
|
|
||||||
* If it doesn't get removed, the linker will complain
|
|
||||||
* loudly with a reasonably clear error message..
|
|
||||||
*/
|
|
||||||
if (idx >= __end_of_fixed_addresses)
|
|
||||||
__this_fixmap_does_not_exist();
|
|
||||||
|
|
||||||
return __fix_to_virt(idx);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -279,6 +279,13 @@ struct pv_mmu_ops {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
struct pv_lazy_ops lazy_mode;
|
struct pv_lazy_ops lazy_mode;
|
||||||
|
|
||||||
|
/* dom0 ops */
|
||||||
|
|
||||||
|
/* Sometimes the physical address is a pfn, and sometimes its
|
||||||
|
an mfn. We can tell which is which from the index. */
|
||||||
|
void (*set_fixmap)(unsigned /* enum fixed_addresses */ idx,
|
||||||
|
unsigned long phys, pgprot_t flags);
|
||||||
};
|
};
|
||||||
|
|
||||||
/* This contains all the paravirt structures: we get a convenient
|
/* This contains all the paravirt structures: we get a convenient
|
||||||
|
@ -1295,6 +1302,12 @@ static inline void arch_flush_lazy_mmu_mode(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void __set_fixmap(unsigned /* enum fixed_addresses */ idx,
|
||||||
|
unsigned long phys, pgprot_t flags)
|
||||||
|
{
|
||||||
|
pv_mmu_ops.set_fixmap(idx, phys, flags);
|
||||||
|
}
|
||||||
|
|
||||||
void _paravirt_nop(void);
|
void _paravirt_nop(void);
|
||||||
#define paravirt_nop ((void *)_paravirt_nop)
|
#define paravirt_nop ((void *)_paravirt_nop)
|
||||||
|
|
||||||
|
|
|
@ -313,6 +313,9 @@ int phys_mem_access_prot_allowed(struct file *file, unsigned long pfn,
|
||||||
unsigned long size, pgprot_t *vma_prot);
|
unsigned long size, pgprot_t *vma_prot);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* Install a pte for a particular vaddr in kernel space. */
|
||||||
|
void set_pte_vaddr(unsigned long vaddr, pte_t pte);
|
||||||
|
|
||||||
#ifdef CONFIG_PARAVIRT
|
#ifdef CONFIG_PARAVIRT
|
||||||
#include <asm/paravirt.h>
|
#include <asm/paravirt.h>
|
||||||
#else /* !CONFIG_PARAVIRT */
|
#else /* !CONFIG_PARAVIRT */
|
||||||
|
|
Loading…
Reference in a new issue