diff options
author | Jeremy Fitzhardinge <jeremy@goop.org> | 2008-06-25 00:19:20 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2008-07-08 07:11:08 -0400 |
commit | 7c934d3990aa4d785feddcef700f4c2c4aba2251 (patch) | |
tree | 6fb0b00811039239a585e256791d2cf80149cc96 /arch/x86/mm/init_64.c | |
parent | 4f9c11dd49fb73e1ec088b27ed6539681a445988 (diff) |
x86, 64-bit: create small vmemmap mappings if PSE not available
If PSE is not available, then fall back to 4k page mappings for the
vmemmap area.
Signed-off-by: Jeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com>
Cc: xen-devel <xen-devel@lists.xensource.com>
Cc: Stephen Tweedie <sct@redhat.com>
Cc: Eduardo Habkost <ehabkost@redhat.com>
Cc: Mark McLoughlin <markmc@redhat.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'arch/x86/mm/init_64.c')
-rw-r--r-- | arch/x86/mm/init_64.c | 62 |
1 files changed, 40 insertions, 22 deletions
diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c index 363751dc3fb8..e62cbdd4e2d9 100644 --- a/arch/x86/mm/init_64.c +++ b/arch/x86/mm/init_64.c | |||
@@ -988,7 +988,7 @@ vmemmap_populate(struct page *start_page, unsigned long size, int node) | |||
988 | pmd_t *pmd; | 988 | pmd_t *pmd; |
989 | 989 | ||
990 | for (; addr < end; addr = next) { | 990 | for (; addr < end; addr = next) { |
991 | next = pmd_addr_end(addr, end); | 991 | void *p = NULL; |
992 | 992 | ||
993 | pgd = vmemmap_pgd_populate(addr, node); | 993 | pgd = vmemmap_pgd_populate(addr, node); |
994 | if (!pgd) | 994 | if (!pgd) |
@@ -998,33 +998,51 @@ vmemmap_populate(struct page *start_page, unsigned long size, int node) | |||
998 | if (!pud) | 998 | if (!pud) |
999 | return -ENOMEM; | 999 | return -ENOMEM; |
1000 | 1000 | ||
1001 | pmd = pmd_offset(pud, addr); | 1001 | if (!cpu_has_pse) { |
1002 | if (pmd_none(*pmd)) { | 1002 | next = (addr + PAGE_SIZE) & PAGE_MASK; |
1003 | pte_t entry; | 1003 | pmd = vmemmap_pmd_populate(pud, addr, node); |
1004 | void *p; | 1004 | |
1005 | if (!pmd) | ||
1006 | return -ENOMEM; | ||
1007 | |||
1008 | p = vmemmap_pte_populate(pmd, addr, node); | ||
1005 | 1009 | ||
1006 | p = vmemmap_alloc_block(PMD_SIZE, node); | ||
1007 | if (!p) | 1010 | if (!p) |
1008 | return -ENOMEM; | 1011 | return -ENOMEM; |
1009 | 1012 | ||
1010 | entry = pfn_pte(__pa(p) >> PAGE_SHIFT, | 1013 | addr_end = addr + PAGE_SIZE; |
1011 | PAGE_KERNEL_LARGE); | 1014 | p_end = p + PAGE_SIZE; |
1012 | set_pmd(pmd, __pmd(pte_val(entry))); | ||
1013 | |||
1014 | /* check to see if we have contiguous blocks */ | ||
1015 | if (p_end != p || node_start != node) { | ||
1016 | if (p_start) | ||
1017 | printk(KERN_DEBUG " [%lx-%lx] PMD -> [%p-%p] on node %d\n", | ||
1018 | addr_start, addr_end-1, p_start, p_end-1, node_start); | ||
1019 | addr_start = addr; | ||
1020 | node_start = node; | ||
1021 | p_start = p; | ||
1022 | } | ||
1023 | addr_end = addr + PMD_SIZE; | ||
1024 | p_end = p + PMD_SIZE; | ||
1025 | } else { | 1015 | } else { |
1026 | vmemmap_verify((pte_t *)pmd, node, addr, next); | 1016 | next = pmd_addr_end(addr, end); |
1017 | |||
1018 | pmd = pmd_offset(pud, addr); | ||
1019 | if (pmd_none(*pmd)) { | ||
1020 | pte_t entry; | ||
1021 | |||
1022 | p = vmemmap_alloc_block(PMD_SIZE, node); | ||
1023 | if (!p) | ||
1024 | return -ENOMEM; | ||
1025 | |||
1026 | entry = pfn_pte(__pa(p) >> PAGE_SHIFT, | ||
1027 | PAGE_KERNEL_LARGE); | ||
1028 | set_pmd(pmd, __pmd(pte_val(entry))); | ||
1029 | |||
1030 | addr_end = addr + PMD_SIZE; | ||
1031 | p_end = p + PMD_SIZE; | ||
1032 | |||
1033 | /* check to see if we have contiguous blocks */ | ||
1034 | if (p_end != p || node_start != node) { | ||
1035 | if (p_start) | ||
1036 | printk(KERN_DEBUG " [%lx-%lx] PMD -> [%p-%p] on node %d\n", | ||
1037 | addr_start, addr_end-1, p_start, p_end-1, node_start); | ||
1038 | addr_start = addr; | ||
1039 | node_start = node; | ||
1040 | p_start = p; | ||
1041 | } | ||
1042 | } else | ||
1043 | vmemmap_verify((pte_t *)pmd, node, addr, next); | ||
1027 | } | 1044 | } |
1045 | |||
1028 | } | 1046 | } |
1029 | return 0; | 1047 | return 0; |
1030 | } | 1048 | } |