x86_64 Relocatable bzImage support (V4)
Subsystems (3)
cover x86_64 Relocatable bzImage support (V4)
Hi,
Here is another attempt on x86_64 relocatable bzImage patches(V4). This patchset makes a bzImage relocatable and same kernel binary can be loaded and run from different physical addresses.
As on now, this mainly helps distros who have to ship an extra kernel compiled for a different physical address to capture the kernel crash dump. This patchset will allow distros and kdump users to use production kernel itself as dump capture kernel and there is no need to ship/build an extra kernel. I am hopeful people will find other interesting usages down the line.
Eric has done all the heavy weight lifting requird to make this patchset work. Last time I posted this patchset (V3), there were minor comments which I have taken care of. Following are the changes since V3.
- Reduced the usage of _AC() macro to only shift operations, as per Andi's comment.
- Restored the CONFIG_PHYSICAL_START option.
- Fixed few bugs with suspend to disk code path.
It would be good if these patches get into -mm so that it can undergo more testing. I have been testing them and these just work fine for me.
Thanks
Vivek
PATCH 1/20 x86_64: Assembly safe page.h and pgtable.h
This patch makes pgtable.h and page.h safe to include in assembly files like head.S. Allowing us to use symbolic constants instead of hard coded numbers when refering to the page tables.
This patch copies asm-sparc64/const.h to asm-x86_64 to get a definition of _AC() a very convinient macro that allows us to force the type when we are compiling the code in C and to drop all of the type information when we are using the constant in assembly. Previously this was done with multiple definition of the same constant. const.h was modified slightly so that it works when given CONFIG options as arguments.
This patch adds #ifndef __ASSEMBLY__ ... #endif and _AC(1,UL) where appropriate so the assembler won't choke on the header files. Otherwise nothing should have changed.
---
include/asm-x86_64/const.h | 20 ++++++++++++++++++++ include/asm-x86_64/page.h | 28 ++++++++++------------------ include/asm-x86_64/pgtable.h | 33 +++++++++++++++++++++------------ 3 files changed, 51 insertions(+), 30 deletions(-)
include/asm-x86_64/const.h new file +20 -0
@@ -0,0 +1,20 @@ +/* const.h: Macros for dealing with constants. */ + +#ifndef _X86_64_CONST_H +#define _X86_64_CONST_H + +/* Some constant macros are used in both assembler and +* C code. Therefore we cannot annotate them always with +* 'UL' and other type specificers unilaterally. We +* use the following macros to deal with this. +*/ + +#ifdef __ASSEMBLY__ +#define _AC (X ,Y ) X +#else +#define __AC (X ,Y ) (X##Y) +#define _AC (X ,Y ) __AC(X,Y) +#endif + + +#endif /* !(_X86_64_CONST_H) */
include/asm-x86_64/page.h renamed from include/asm-x86_64/page.h~x86_64-Assembly-safe-page.h-and-pgtable.h +10 -18
@@ -1,14 +1,11 @@#ifndef _X86_64_PAGE_H#define _X86_64_PAGE_H +#include <asm/const.h> /* PAGE_SHIFT determines the page size */ #define PAGE_SHIFT 12 -#ifdef __ASSEMBLY__ -#define PAGE_SIZE (0x1 << PAGE_SHIFT) -#else -#define PAGE_SIZE (1UL << PAGE_SHIFT) -#endif +#define PAGE_SIZE (_AC(1,UL) << PAGE_SHIFT)#define PAGE_MASK (~(PAGE_SIZE-1))#define PHYSICAL_PAGE_MASK (~(PAGE_SIZE-1) & __PHYSICAL_MASK)
@@ -33,10 +30,10 @@#define N_EXCEPTION_STACKS 5/* hw limit: 7 */ #define LARGE_PAGE_MASK (~(LARGE_PAGE_SIZE-1)) -#define LARGE_PAGE_SIZE (1UL << PMD_SHIFT) +#define LARGE_PAGE_SIZE (_AC(1,UL) << PMD_SHIFT)#define HPAGE_SHIFT PMD_SHIFT -#define HPAGE_SIZE ((1UL) << HPAGE_SHIFT) +#define HPAGE_SIZE (_AC(1,UL) << HPAGE_SHIFT)#define HPAGE_MASK (~(HPAGE_SIZE - 1))#define HUGETLB_PAGE_ORDER (HPAGE_SHIFT - PAGE_SHIFT)
@@ -76,29 +73,24 @@ typedef struct { unsigned long pgprot; }#define __pgd (x) ((pgd_t) { (x) } )#define __pgprot (x) ((pgprot_t) { (x) } ) -#define __PHYSICAL_START ((unsigned long)CONFIG_PHYSICAL_START) -#define __START_KERNEL (__START_KERNEL_map + __PHYSICAL_START) -#define __START_KERNEL_map 0xffffffff80000000UL -#define __PAGE_OFFSET 0xffff810000000000UL +#endif /* !__ASSEMBLY__ */ -#else #define __PHYSICAL_START CONFIG_PHYSICAL_START#define __START_KERNEL (__START_KERNEL_map + __PHYSICAL_START)#define __START_KERNEL_map 0xffffffff80000000#define __PAGE_OFFSET 0xffff810000000000 -#endif /* !__ASSEMBLY__ */ /* to align the pointer to the (next) page boundary */ #define PAGE_ALIGN (addr) (((addr)+PAGE_SIZE-1)&PAGE_MASK)/* See Documentation/x86_64/mm.txt for a description of the memory map. */ #define __PHYSICAL_MASK_SHIFT 46 -#define __PHYSICAL_MASK ((1UL << __PHYSICAL_MASK_SHIFT) - 1) +#define __PHYSICAL_MASK ((_AC(1,UL) << __PHYSICAL_MASK_SHIFT) - 1)#define __VIRTUAL_MASK_SHIFT 48 -#define __VIRTUAL_MASK ((1UL << __VIRTUAL_MASK_SHIFT) - 1) +#define __VIRTUAL_MASK ((_AC(1,UL) << __VIRTUAL_MASK_SHIFT) - 1) -#define KERNEL_TEXT_SIZE (40UL*1024*1024) -#define KERNEL_TEXT_START 0xffffffff80000000UL +#define KERNEL_TEXT_SIZE (40*1024*1024) +#define KERNEL_TEXT_START 0xffffffff80000000#ifndef __ASSEMBLY__
@@ -106,7 +98,7 @@ typedef struct { unsigned long pgprot; }#endif /* __ASSEMBLY__ */ -#define PAGE_OFFSET ((unsigned long)__PAGE_OFFSET) +#define PAGE_OFFSET __PAGE_OFFSET/* Note: __pa(&symbol_visible_to_c) should be always replaced with __pa_symbol. Otherwise you risk miscompilation. */
include/asm-x86_64/pgtable.h renamed from include/asm-x86_64/pgtable.h~x86_64-Assembly-safe-page.h-and-pgtable.h +21 -12
@@ -1,6 +1,9 @@#ifndef _X86_64_PGTABLE_H#define _X86_64_PGTABLE_H +#include <asm/const.h> +#ifndef __ASSEMBLY__ +/* * This file contains the functions and defines necessary to modify and use * the x86-64 page table tree.
@@ -31,6 +34,8 @@ extern void clear_kernel_mapping(unsigneextern unsigned long empty_zero_page[PAGE_SIZE /sizeof (unsigned long )];#define ZERO_PAGE (vaddr) (virt_to_page(empty_zero_page)) +#endif /* !__ASSEMBLY__ */ +/* * PGDIR_SHIFT determines what a top-level page table entry can map */
@@ -55,6 +60,8 @@ extern unsigned long empty_zero_page[PAG*/ #define PTRS_PER_PTE 512 +#ifndef __ASSEMBLY__ +#define pte_ERROR (e) \ printk("%s:%d: bad pte %p(%016lx).\n", __FILE__, __LINE__, &(e), pte_val(e))#define pmd_ERROR (e) \
@@ -118,22 +125,23 @@ static inline pte_t ptep_get_and_clear_f#define pte_pgprot (a) (__pgprot((a).pte & ~PHYSICAL_PAGE_MASK)) -#define PMD_SIZE (1UL << PMD_SHIFT) +#endif /* !__ASSEMBLY__ */ + +#define PMD_SIZE (_AC(1,UL) << PMD_SHIFT)#define PMD_MASK (~(PMD_SIZE-1)) -#define PUD_SIZE (1UL << PUD_SHIFT) +#define PUD_SIZE (_AC(1,UL) << PUD_SHIFT)#define PUD_MASK (~(PUD_SIZE-1)) -#define PGDIR_SIZE (1UL << PGDIR_SHIFT) +#define PGDIR_SIZE (_AC(1,UL) << PGDIR_SHIFT)#define PGDIR_MASK (~(PGDIR_SIZE-1))#define USER_PTRS_PER_PGD ((TASK_SIZE-1)/PGDIR_SIZE+1)#define FIRST_USER_ADDRESS 0 -#ifndef __ASSEMBLY__ -#define MAXMEM 0x3fffffffffffUL -#define VMALLOC_START 0xffffc20000000000UL -#define VMALLOC_END 0xffffe1ffffffffffUL -#define MODULES_VADDR 0xffffffff88000000UL -#define MODULES_END 0xfffffffffff00000UL +#define MAXMEM 0x3fffffffffff +#define VMALLOC_START 0xffffc20000000000 +#define VMALLOC_END 0xffffe1ffffffffff +#define MODULES_VADDR 0xffffffff88000000 +#define MODULES_END 0xfffffffffff00000#define MODULES_LEN (MODULES_END - MODULES_VADDR)#define _PAGE_BIT_PRESENT 0
@@ -159,7 +167,7 @@ static inline pte_t ptep_get_and_clear_f#define _PAGE_GLOBAL 0x100/* Global TLB entry */ #define _PAGE_PROTNONE 0x080/* If not present */ -#define _PAGE_NX (1UL<<_PAGE_BIT_NX) +#define _PAGE_NX (_AC(1,UL)<<_PAGE_BIT_NX)#define _PAGE_TABLE (_PAGE_PRESENT | _PAGE_RW | _PAGE_USER | _PAGE_ACCESSED | _PAGE_DIRTY)#define _KERNPG_TABLE (_PAGE_PRESENT | _PAGE_RW | _PAGE_ACCESSED | _PAGE_DIRTY)
@@ -221,6 +229,8 @@ static inline pte_t ptep_get_and_clear_f#define __S110 PAGE_SHARED_EXEC#define __S111 PAGE_SHARED_EXEC +#ifndef __ASSEMBLY__ +static inline unsigned long pgd_bad (pgd_t pgd) {return pgd_val (pgd) & ~(PTE_MASK | _KERNPG_TABLE | _PAGE_USER);
@@ -406,8 +416,6 @@ extern spinlock_t pgd_lock;extern struct page *pgd_list;void vmalloc_sync_all (void ); -#endif /* !__ASSEMBLY__ */ -extern int kern_addr_valid (unsigned long addr);#define io_remap_pfn_range (vma, vaddr, pfn, size, prot) \
@@ -437,5 +445,6 @@ extern int kern_addr_valid(unsigned long#define __HAVE_ARCH_PTEP_SET_WRPROTECT#define __HAVE_ARCH_PTE_SAME#include <asm-generic/pgtable.h> +#endif /* !__ASSEMBLY__ */ #endif /* _X86_64_PGTABLE_H */
_
Re: [PATCH 1/20] x86_64: Assembly safe page.h and pgtable.h
Quoted 7 lines · Vivek Goyal
This patch makes
pgtable.handpage.hsafe to include in assembly files likehead.S. Allowing us to use symbolic constants instead of hard coded numbers when refering to the page tables.
Quoted 5 lines
This patch copies
asm-sparc64/const.hto asm-x86_64 to get a definition of_AC()a very convinient macro that allows us to force the type when we are compiling the code in C and to drop all of the type information when we are using the constant in assembly.
Should this file not live in asm-generic and be useable for all architectures?
Sam
Re: [PATCH 1/20] x86_64: Assembly safe page.h and pgtable.h
Quoted 8 lines · Sam Ravnborg
Quoted 7 lines · Vivek Goyal
This patch makes
pgtable.handpage.hsafe to include in assembly files likehead.S. Allowing us to use symbolic constants instead of hard coded numbers when refering to the page tables.
Quoted 8 lines
Quoted 5 lines
This patch copies
asm-sparc64/const.hto asm-x86_64 to get a definition of_AC()a very convinient macro that allows us to force the type when we are compiling the code in C and to drop all of the type information when we are using the constant in assembly.Should this file not live in asm-generic and be useable for all architectures?
Hi Sam,
Thanks for the review. This makes sense to me. Move const.h into asm-generic and let everybody use it.
This is more of a small cleanup issue and involves changing few header files in asm-sparc64 and make sure nothing is broken on sparc64. This patchset is already becoming big and complex. Is it ok if we let the patch remain unmodified for now and once this gets in and settles down, I can post another patch to do above modification?
Thanks
Vivek
Re: [PATCH 1/20] x86_64: Assembly safe page.h and pgtable.h
Quoted 10 lines · Vivek Goyal
Hi Sam,
Thanks for the review. This makes sense to me. Move
const.hinto asm-generic and let everybody use it.This is more of a small cleanup issue and involves changing few header files in asm-sparc64 and make sure nothing is broken on sparc64. This patchset is already becoming big and complex. Is it ok if we let the patch remain unmodified for now and once this gets in and settles down, I can post another patch to do above modification?
Actually unless there is a reason not to, we can probably move this into include/linux instead of include/asm-generic. I don't see anything in that header file that is architecture specific in any way. Except that it happens to only be used in architecture specific code.
Eric
PATCH 2/20 x86_64: Kill temp boot pmds
In reply to Vivek GoyalEarly in the boot process we need the ability to set up temporary mappings, before our normal mechanisms are initialized. Currently this is used to map pages that are part of the page tables we are building and pages during the dmi scan.
The core problem is that we are using the user portion of the page tables to implement this. Which means that while this mechanism is active we cannot catch NULL pointer dereferences and we deviate from the normal ways of handling things.
In this patch I modify early_ioremap to map pages into the kernel portion of address space, roughly where we will later put modules, and I make the discovery of which addresses we can use dynamic which removes all kinds of static limits and remove the dependencies on implementation details between different parts of the code.
Now alloc_low_page() and unmap_low_page() use early_iomap() and early_iounmap() to allocate/map and unmap a page.
---
arch/x86_64/kernel/head.S | 3 - arch/x86_64/mm/init.c | 100 ++++++++++++++++++++-------------------------- 2 files changed, 45 insertions(+), 58 deletions(-)
arch/x86_64/kernel/head.S renamed from arch/x86_64/kernel/head.S~x86_64-Kill-temp_boot_pmds +0 -3
@@ -288,9 +288,6 @@ NEXT_PAGE(level2_ident_pgt) .quad i << 21 | 0x083 i = i + 1 .endr - /* Temporary mappings for the super early allocator in arch/x86_64/mm/init.c */ - .globl temp_boot_pmds -temp_boot_pmds: .fill 492,8,0 NEXT_PAGE(level2_kernel_pgt)
arch/x86_64/mm/init.c renamed from arch/x86_64/mm/init.c~x86_64-Kill-temp_boot_pmds +45 -55
165 lines not on this page · raw message
_
PATCH 3/20 x86_64: Clean up the early boot page table
In reply to Vivek Goyal- Merge physmem_pgt and ident_pgt, removing physmem_pgt. The merge is broken as soon as mm/init.c:init_memory_mapping is run.
- As physmem_pgt is gone don't export it in pgtable.h.
- Use defines from pgtable.h for page permissions.
- Fix the physical memory identity mapping so it is at the correct address.
- Remove the physical memory mapping from wakeup_level4_pgt it is at the wrong address so we can't possibly be usinging it.
- Simply NEXT_PAGE the work to calculate the phys_ alias of the labels was very cool. Unfortuantely it was a brittle special purpose hack that makes maitenance more difficult. Instead just use label - __START_KERNEL_map like we do everywhere else in assembly.
---
arch/x86_64/kernel/head.S | 61 +++++++++++++++++++------------------------ include/asm-x86_64/pgtable.h | 1 2 files changed, 28 insertions(+), 34 deletions(-)
arch/x86_64/kernel/head.S renamed from arch/x86_64/kernel/head.S~x86_64-Cleanup-the-early-boot-page-table +28 -33
@@ -13,6 +13,7 @@ #include <linux/init.h> #include <asm/desc.h> #include <asm/segment.h> +#include <asm/pgtable.h> #include <asm/page.h> #include <asm/msr.h> #include <asm/cache.h>
@@ -260,52 +261,48 @@ ljumpvector: ENTRY(stext) ENTRY(_stext) - $page = 0 #define NEXT_PAGE(name) \ - $page = $page + 1; \ - .org $page * 0x1000; \ - phys_/**/name = $page * 0x1000 + __PHYSICAL_START; \ + .balign PAGE_SIZE; \ ENTRY(name) +/* Automate the creation of 1 to 1 mapping pmd entries */ +#define PMDS(START, PERM, COUNT) \ + i = 0 ; \ + .rept (COUNT) ; \ + .quad (START) + (i << 21) + (PERM) ; \ + i = i + 1 ; \ + .endr + NEXT_PAGE(init_level4_pgt) /* This gets initialized in x86_64_start_kernel */ .fill 512,8,0 NEXT_PAGE(level3_ident_pgt) - .quad phys_level2_ident_pgt | 0x007 + .quad level2_ident_pgt - __START_KERNEL_map + _KERNPG_TABLE .fill 511,8,0 NEXT_PAGE(level3_kernel_pgt) .fill 510,8,0 /* (2^48-(2*1024*1024*1024)-((2^39)*511))/(2^30) = 510 */ - .quad phys_level2_kernel_pgt | 0x007 + .quad level2_kernel_pgt - __START_KERNEL_map + _KERNPG_TABLE .fill 1,8,0 NEXT_PAGE(level2_ident_pgt) - /* 40MB for bootup. */ - i = 0 - .rept 20 - .quad i << 21 | 0x083 - i = i + 1 - .endr - .fill 492,8,0 + /* Since I easily can, map the first 1G. + * Don't set NX because code runs from these pages. + */ + PMDS(0x0000000000000000, __PAGE_KERNEL_LARGE_EXEC, PTRS_PER_PMD) NEXT_PAGE(level2_kernel_pgt) /* 40MB kernel mapping. The kernel code cannot be bigger than that. When you change this change KERNEL_TEXT_SIZE in page.h too. */ /* (2^48-(2*1024*1024*1024)-((2^39)*511)-((2^30)*510)) = 0 */ - i = 0 - .rept 20 - .quad i << 21 | 0x183 - i = i + 1 - .endr + PMDS(0x0000000000000000, __PAGE_KERNEL_LARGE_EXEC|_PAGE_GLOBAL, + KERNEL_TEXT_SIZE/PMD_SIZE) /* Module mapping starts here */ - .fill 492,8,0 - -NEXT_PAGE(level3_physmem_pgt) - .quad phys_level2_kernel_pgt | 0x007 /* so that __va works even before pagetable_init */ - .fill 511,8,0 + .fill (PTRS_PER_PMD - (KERNEL_TEXT_SIZE/PMD_SIZE)),8,0 +#undef PMDS #undef NEXT_PAGE .data
@@ -313,12 +310,10 @@ NEXT_PAGE(level3_physmem_pgt) #ifdef CONFIG_ACPI_SLEEP .align PAGE_SIZE ENTRY(wakeup_level4_pgt) - .quad phys_level3_ident_pgt | 0x007 - .fill 255,8,0 - .quad phys_level3_physmem_pgt | 0x007 - .fill 254,8,0 + .quad level3_ident_pgt - __START_KERNEL_map + _KERNPG_TABLE + .fill 510,8,0 /* (2^48-(2*1024*1024*1024))/(2^39) = 511 */ - .quad phys_level3_kernel_pgt | 0x007 + .quad level3_kernel_pgt - __START_KERNEL_map + _KERNPG_TABLE #endif #ifndef CONFIG_HOTPLUG_CPU
@@ -332,12 +327,12 @@ ENTRY(wakeup_level4_pgt) */ .align PAGE_SIZE ENTRY(boot_level4_pgt) - .quad phys_level3_ident_pgt | 0x007 - .fill 255,8,0 - .quad phys_level3_physmem_pgt | 0x007 - .fill 254,8,0 + .quad level3_ident_pgt - __START_KERNEL_map + _KERNPG_TABLE + .fill 257,8,0 + .quad level3_ident_pgt - __START_KERNEL_map + _KERNPG_TABLE + .fill 252,8,0 /* (2^48-(2*1024*1024*1024))/(2^39) = 511 */ - .quad phys_level3_kernel_pgt | 0x007 + .quad level3_kernel_pgt - __START_KERNEL_map + _PAGE_TABLE .data
include/asm-x86_64/pgtable.h renamed from include/asm-x86_64/pgtable.h~x86_64-Cleanup-the-early-boot-page-table +0 -1
@@ -15,7 +15,6 @@#include <asm/pda.h> extern pud_t level3_kernel_pgt[512 ]; -extern pud_t level3_physmem_pgt[512 ];extern pud_t level3_ident_pgt[512 ];extern pmd_t level2_kernel_pgt[512 ];extern pgd_t init_level4_pgt[];
_
PATCH 4/20 x86_64: Fix early printk to use standard ISA mapping
In reply to Vivek Goyal---
arch/x86_64/kernel/early_printk.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
arch/x86_64/kernel/early_printk.c renamed from arch/x86_64/kernel/early_printk.c~x86_64-fix-early_printk-to-use-the-standard-ISA-mapping +1 -2
@@ -11,11 +11,10 @@#ifdef __i386__#include <asm/setup.h> -#define VGABASE (__ISA_IO_base + 0xb8000)#else #include <asm/bootsetup.h> -#define VGABASE ((void __iomem *)0xffffffff800b8000UL)#endif +#define VGABASE (__ISA_IO_base + 0xb8000)static int max_ypos =25 , max_xpos =80 ;static int current_ypos =25 , current_xpos =0 ;
_
PATCH 5/20 x86_64: modify copy_bootdata to use virtual addresses
In reply to Vivek GoyalUse virtual addresses instead of physical addresses in copy bootdata. In addition fix the implementation of the old bootloader convention. Everything is at real_mode_data always. It is just that sometimes real_mode_data was relocated by setup.S to not sit at 0x90000.
---
arch/x86_64/kernel/head64.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-)
arch/x86_64/kernel/head64.c renamed from arch/x86_64/kernel/head64.c~x86_64-modify-copy_bootdata-to-use-virtual-addresses +8 -9
@@ -29,25 +29,24 @@ static void __init clear_bss(void) }#define NEW_CL_POINTER 0x228/* Relative to real mode data */ -#define OLD_CL_MAGIC_ADDR 0x90020 +#define OLD_CL_MAGIC_ADDR 0x20#define OLD_CL_MAGIC 0xA33F -#define OLD_CL_BASE_ADDR 0x90000 -#define OLD_CL_OFFSET 0x90022 +#define OLD_CL_OFFSET 0x22static void __init copy_bootdata (char *real_mode_data) { -int new_data; +unsigned long new_data;char * command_line;memcpy (x86_boot_params, real_mode_data,BOOT_PARAM_SIZE ); - new_data = *(int *) (x86_boot_params +NEW_CL_POINTER ); + new_data = *(u32 *) (x86_boot_params +NEW_CL_POINTER );if (!new_data) { -if (OLD_CL_MAGIC != * (u16 *)OLD_CL_MAGIC_ADDR ) { +if (OLD_CL_MAGIC != *(u16 *)(real_mode_data +OLD_CL_MAGIC_ADDR )) {return ; } - new_data =OLD_CL_BASE_ADDR + * (u16 *)OLD_CL_OFFSET ; + new_data =__pa (real_mode_data) + *(u16 *)(real_mode_data +OLD_CL_OFFSET ); } - command_line = (char *) ((u64)(new_data)); + command_line =__va (new_data);memcpy (boot_command_line, command_line,COMMAND_LINE_SIZE ); }
@@ -74,7 +73,7 @@ void __init x86_64_start_kernel(char * rcpu_pda (i) = &boot_cpu_pda[i];pda_init (0 ); -copy_bootdata (real_mode_data); +copy_bootdata (__va (real_mode_data));#ifdef CONFIG_SMP cpu_set (0 , cpu_online_map);#endif
_
PATCH 6/20 x86_64: cleanup segments
In reply to Vivek GoyalMove __KERNEL32_CS up into the unused gdt entry. __KERNEL32_CS is used when entering the kernel so putting it first is useful when trying to keep boot gdt sizes to a minimum.
Set the accessed bit on all gdt entries. We don't care so there is no need for the cpu to burn the extra cycles, and it potentially allows the pages to be immutable. Plus it is confusing when debugging and your gdt entries mysteriously change.
---
arch/x86_64/kernel/head.S | 12 ++++++------ include/asm-x86_64/segment.h | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-)
arch/x86_64/kernel/head.S renamed from arch/x86_64/kernel/head.S~x86_64-cleanup-segments +6 -6
@@ -362,13 +362,13 @@ gdt: ENTRY(cpu_gdt_table) .quad 0x0000000000000000 /* NULL descriptor */ + .quad 0x00cf9b000000ffff /* __KERNEL32_CS */ + .quad 0x00af9b000000ffff /* __KERNEL_CS */ + .quad 0x00cf93000000ffff /* __KERNEL_DS */ + .quad 0x00cffb000000ffff /* __USER32_CS */ + .quad 0x00cff3000000ffff /* __USER_DS, __USER32_DS */ + .quad 0x00affb000000ffff /* __USER_CS */ .quad 0x0 /* unused */ - .quad 0x00af9a000000ffff /* __KERNEL_CS */ - .quad 0x00cf92000000ffff /* __KERNEL_DS */ - .quad 0x00cffa000000ffff /* __USER32_CS */ - .quad 0x00cff2000000ffff /* __USER_DS, __USER32_DS */ - .quad 0x00affa000000ffff /* __USER_CS */ - .quad 0x00cf9a000000ffff /* __KERNEL32_CS */ .quad 0,0 /* TSS */ .quad 0,0 /* LDT */ .quad 0,0,0 /* three TLS descriptors */
include/asm-x86_64/segment.h renamed from include/asm-x86_64/segment.h~x86_64-cleanup-segments +1 -1
@@ -6,7 +6,7 @@#define __KERNEL_CS 0x10#define __KERNEL_DS 0x18 -#define __KERNEL32_CS 0x38 +#define __KERNEL32_CS 0x08/* * we cannot use the same code segment descriptor for user and kernel
_
PATCH 7/20 x86_64: Add EFER to the register set saved by save_processor_state
In reply to Vivek GoyalEFER varies like %cr4 depending on the cpu capabilities, and which cpu capabilities we want to make use of. So save/restore it make certain we have the same EFER value when we are done.
---
arch/x86_64/kernel/suspend.c | 3 ++- include/asm-x86_64/suspend.h | 1 + 2 files changed, 3 insertions(+), 1 deletion(-)
arch/x86_64/kernel/suspend.c renamed from arch/x86_64/kernel/suspend.c~x86_64-Add-EFER-to-the-set-registers-saved-by-save_processor_state +2 -1
@@ -33,7 +33,6 @@ void __save_processor_state(struct saved asmvolatile ("str %0" :"=m" (ctxt->tr));/* XMM0..XMM15 should be handled by kernel_fpu_begin(). */ -/* EFER should be constant for kernel version, no need to handle it. */ /* * segment registers */
@@ -50,6 +49,7 @@ void __save_processor_state(struct saved/* * control registers */ +rdmsrl (MSR_EFER , ctxt->efer); asmvolatile ("movq %%cr0, %0" :"=r" (ctxt->cr0)); asmvolatile ("movq %%cr2, %0" :"=r" (ctxt->cr2)); asmvolatile ("movq %%cr3, %0" :"=r" (ctxt->cr3));
@@ -75,6 +75,7 @@ void __restore_processor_state(struct sa/* * control registers */ +wrmsrl (MSR_EFER , ctxt->efer); asmvolatile ("movq %0, %%cr8" ::"r" (ctxt->cr8)); asmvolatile ("movq %0, %%cr4" ::"r" (ctxt->cr4)); asmvolatile ("movq %0, %%cr3" ::"r" (ctxt->cr3));
include/asm-x86_64/suspend.h renamed from include/asm-x86_64/suspend.h~x86_64-Add-EFER-to-the-set-registers-saved-by-save_processor_state +1 -0
@@ -17,6 +17,7 @@ struct saved_context {u16 ds, es, fs, gs, ss;unsigned long gs_base, gs_kernel_base, fs_base;unsigned long cr0, cr2, cr3, cr4, cr8; +unsigned long efer;u16 gdt_pad;u16 gdt_limit;unsigned long gdt_base;
_
PATCH 8/20 x86_64: 64bit PIC SMP trampoline
In reply to Vivek GoyalThis modifies the SMP trampoline and all of the associated code so it can jump to a 64bit kernel loaded at an arbitrary address.
The dependencies on having an idenetity mapped page in the kernel page tables for SMP bootup have all been removed.
In addition the trampoline has been modified to verify that long mode is supported. Asking if long mode is implemented is down right silly but we have traditionally had some of these checks, and they can't hurt anything. So when the totally ludicrous happens we just might handle it correctly.
---
arch/x86_64/kernel/head.S | 1 arch/x86_64/kernel/setup.c | 9 -- arch/x86_64/kernel/trampoline.S | 168 ++++++++++++++++++++++++++++++++++++---- 3 files changed, 156 insertions(+), 22 deletions(-)
arch/x86_64/kernel/head.S renamed from arch/x86_64/kernel/head.S~x86_64-64bit-PIC-SMP-trampoline +1 -0
@@ -101,6 +101,7 @@ startup_32: .org 0x100 .globl startup_64 startup_64: +ENTRY(secondary_startup_64) /* We come here either from startup_32 * or directly from a 64bit bootloader. * Since we may have come directly from a bootloader we
arch/x86_64/kernel/setup.c renamed from arch/x86_64/kernel/setup.c~x86_64-64bit-PIC-SMP-trampoline +1 -8
@@ -329,15 +329,8 @@ void __init setup_arch(char **cmdline_p)#endif #ifdef CONFIG_SMP -/* -* But first pinch a few for the stack/trampoline stuff -* FIXME: Don't need the extra page at 4K, but need to fix -* trampoline before removing it. (see the GDT stuff) -*/ -reserve_bootmem_generic (PAGE_SIZE ,PAGE_SIZE ); -/* Reserve SMP trampoline */ -reserve_bootmem_generic (SMP_TRAMPOLINE_BASE ,PAGE_SIZE ); +reserve_bootmem_generic (SMP_TRAMPOLINE_BASE ,2 *PAGE_SIZE );#endif #ifdef CONFIG_ACPI_SLEEP
arch/x86_64/kernel/trampoline.S renamed from arch/x86_64/kernel/trampoline.S~x86_64-64bit-PIC-SMP-trampoline +154 -14
213 lines not on this page · raw message
_
PATCH 9/20 x86_64: Get rid of dead code in suspend resume
In reply to Vivek Goyalo Get rid of dead code in wakeup.S
o We never restore from saved_gdt, saved_idt, saved_ltd, saved_tss, saved_cr3, saved_cr4, saved_cr0, real_save_gdt, saved_efer, saved_efer2. Get rid of of associated code.
o Get rid of bogus_magic, bogus_31_magic and bogus_magic2. No longer being used.
---
arch/x86_64/kernel/acpi/wakeup.S | 57 --------------------------------------- 1 file changed, 1 insertion(+), 56 deletions(-)
arch/x86_64/kernel/acpi/wakeup.S renamed from arch/x86_64/kernel/acpi/wakeup.S~x86_64-get-rid-of-dead-code-in-suspend-resume +1 -56
@@ -258,8 +258,6 @@ gdt_48a: .word 0, 0 # gdt base (filled in later) -real_save_gdt: .word 0 - .quad 0 real_magic: .quad 0 video_mode: .quad 0 video_flags: .quad 0
@@ -272,10 +270,6 @@ bogus_32_magic: movb $0xb3,%al ; outb %al,$0x80 jmp bogus_32_magic -bogus_31_magic: - movb $0xb1,%al ; outb %al,$0x80 - jmp bogus_31_magic - bogus_cpu: movb $0xbc,%al ; outb %al,$0x80 jmp bogus_cpu
@@ -346,16 +340,6 @@ check_vesaa: _setbada: jmp setbada - .code64 -bogus_magic: - movw $0x0e00 + 'B', %ds:(0xb8018) - jmp bogus_magic - -bogus_magic2: - movw $0x0e00 + '2', %ds:(0xb8018) - jmp bogus_magic2 - - wakeup_stack_begin: # Stack grows down .org 0xff0
@@ -373,28 +357,11 @@ ENTRY(wakeup_end) # # Returned address is location of code in low memory (past data and stack) # + .code64 ENTRY(acpi_copy_wakeup_routine) pushq %rax - pushq %rcx pushq %rdx - sgdt saved_gdt - sidt saved_idt - sldt saved_ldt - str saved_tss - - movq %cr3, %rdx - movq %rdx, saved_cr3 - movq %cr4, %rdx - movq %rdx, saved_cr4 - movq %cr0, %rdx - movq %rdx, saved_cr0 - sgdt real_save_gdt - wakeup_start (,%rdi) - movl $MSR_EFER, %ecx - rdmsr - movl %eax, saved_efer - movl %edx, saved_efer2 - movl saved_video_mode, %edx movl %edx, video_mode - wakeup_start (,%rdi) movl acpi_video_flags, %edx
@@ -407,17 +374,8 @@ ENTRY(acpi_copy_wakeup_routine) cmpl $0x9abcdef0, %eax jne bogus_32_magic - # make sure %cr4 is set correctly (features, etc) - movl saved_cr4 - __START_KERNEL_map, %eax - movq %rax, %cr4 - - movl saved_cr0 - __START_KERNEL_map, %eax - movq %rax, %cr0 - jmp 1f # Flush pipelines -1: # restore the regs we used popq %rdx - popq %rcx popq %rax ENTRY(do_suspend_lowlevel_s4bios) ret
@@ -512,16 +470,3 @@ ENTRY(saved_eip) .quad 0 ENTRY(saved_esp) .quad 0 ENTRY(saved_magic) .quad 0 - -ALIGN -# saved registers -saved_gdt: .quad 0,0 -saved_idt: .quad 0,0 -saved_ldt: .quad 0 -saved_tss: .quad 0 - -saved_cr0: .quad 0 -saved_cr3: .quad 0 -saved_cr4: .quad 0 -saved_efer: .quad 0 -saved_efer2: .quad 0
_
PATCH 10/20 x86_64: wakeup.S rename registers to reflect right names
In reply to Vivek Goyalo Use appropriate names for 64bit regsiters.
---
arch/x86_64/kernel/acpi/wakeup.S | 36 ++++++++++++++++++------------------ include/asm-x86_64/suspend.h | 12 ++++++------ 2 files changed, 24 insertions(+), 24 deletions(-)
arch/x86_64/kernel/acpi/wakeup.S renamed from arch/x86_64/kernel/acpi/wakeup.S~x86_64-wakeup.S-rename-registers-to-reflect-right-names +18 -18
@@ -211,16 +211,16 @@ wakeup_long64: movw %ax, %es movw %ax, %fs movw %ax, %gs - movq saved_esp, %rsp + movq saved_rsp, %rsp movw $0x0e00 + 'x', %ds:(0xb8018) - movq saved_ebx, %rbx - movq saved_edi, %rdi - movq saved_esi, %rsi - movq saved_ebp, %rbp + movq saved_rbx, %rbx + movq saved_rdi, %rdi + movq saved_rsi, %rsi + movq saved_rbp, %rbp movw $0x0e00 + '!', %ds:(0xb801a) - movq saved_eip, %rax + movq saved_rip, %rax jmp *%rax .code32
@@ -408,13 +408,13 @@ do_suspend_lowlevel: movq %r15, saved_context_r15(%rip) pushfq ; popq saved_context_eflags(%rip) - movq $.L97, saved_eip(%rip) + movq $.L97, saved_rip(%rip) - movq %rsp,saved_esp - movq %rbp,saved_ebp - movq %rbx,saved_ebx - movq %rdi,saved_edi - movq %rsi,saved_esi + movq %rsp,saved_rsp + movq %rbp,saved_rbp + movq %rbx,saved_rbx + movq %rdi,saved_rdi + movq %rsi,saved_rsi addq $8, %rsp movl $3, %edi
@@ -461,12 +461,12 @@ do_suspend_lowlevel: .data ALIGN -ENTRY(saved_ebp) .quad 0 -ENTRY(saved_esi) .quad 0 -ENTRY(saved_edi) .quad 0 -ENTRY(saved_ebx) .quad 0 +ENTRY(saved_rbp) .quad 0 +ENTRY(saved_rsi) .quad 0 +ENTRY(saved_rdi) .quad 0 +ENTRY(saved_rbx) .quad 0 -ENTRY(saved_eip) .quad 0 -ENTRY(saved_esp) .quad 0 +ENTRY(saved_rip) .quad 0 +ENTRY(saved_rsp) .quad 0 ENTRY(saved_magic) .quad 0
include/asm-x86_64/suspend.h renamed from include/asm-x86_64/suspend.h~x86_64-wakeup.S-rename-registers-to-reflect-right-names +6 -6
@@ -45,12 +45,12 @@ extern unsigned long saved_context_eflagextern void fix_processor_context (void );#ifdef CONFIG_ACPI_SLEEP -extern unsigned long saved_eip; -extern unsigned long saved_esp; -extern unsigned long saved_ebp; -extern unsigned long saved_ebx; -extern unsigned long saved_esi; -extern unsigned long saved_edi; +extern unsigned long saved_rip; +extern unsigned long saved_rsp; +extern unsigned long saved_rbp; +extern unsigned long saved_rbx; +extern unsigned long saved_rsi; +extern unsigned long saved_rdi;/* routines for saving/restoring kernel state */ extern int acpi_save_state_mem (void );
_
Re: [PATCH 10/20] x86_64: wakeup.S rename registers to reflect right names
Quoted 6 lines · Vivek Goyal
o Use appropriate names for 64bit regsiters.
Signed-off-by Eric W. Biederman <[email protected]>Signed-off-by Vivek Goyal <[email protected]>
ACK.
Pavel
Signature · 2 lines
(english) http://www.livejournal.com/~pavelmachek (cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
PATCH 11/20 x86_64: wakeup.S misc cleanups
In reply to Vivek Goyalo Various cleanups. One of the main purpose of cleanups is that make wakeup.S as close as possible to trampoline.S.
o Following are the changes
- Indentations for comments.
- Changed the gdt table to compact form and to resemble the one in trampoline.S
- Take the jump to 32bit from real mode using ljmpl. Makes code more readable.
- After enabling long mode, directly take a long jump for 64bit mode. No need to take an extra jump to "reach_comaptibility_mode"
- Stack is not used after real mode. So don't load stack in 32 bit mode.
- No need to enable PGE here.
- No need to do extra EFER read, anyway we trash the read contents.
- No need to enable system call (EFER_SCE). Anyway it will be enabled when original EFER is restored.
- No need to set MP, ET, NE, WP, AM bits in cr0. Very soon we will reload the original cr0 while restroing the processor state.
---
arch/x86_64/kernel/acpi/wakeup.S | 112 +++++++++++++-------------------------- 1 file changed, 40 insertions(+), 72 deletions(-)
arch/x86_64/kernel/acpi/wakeup.S renamed from arch/x86_64/kernel/acpi/wakeup.S~x86_64-wakeup.S-misc-cleanups +40 -72
@@ -30,11 +30,12 @@ wakeup_code: cld # setup data segment movw %cs, %ax - movw %ax, %ds # Make ds:0 point to wakeup_start + movw %ax, %ds # Make ds:0 point to wakeup_start movw %ax, %ss - mov $(wakeup_stack - wakeup_code), %sp # Private stack is needed for ASUS board + # Private stack is needed for ASUS board + mov $(wakeup_stack - wakeup_code), %sp - pushl $0 # Kill any dangerous flags + pushl $0 # Kill any dangerous flags popfl movl real_magic - wakeup_code, %eax
@@ -45,7 +46,7 @@ wakeup_code: jz 1f lcall $0xc000,$3 movw %cs, %ax - movw %ax, %ds # Bios might have played with that + movw %ax, %ds # Bios might have played with that movw %ax, %ss 1:
@@ -75,9 +76,12 @@ wakeup_code: jmp 1f 1: - .byte 0x66, 0xea # prefix + jmpi-opcode - .long wakeup_32 - __START_KERNEL_map - .word __KERNEL_CS + ljmpl *(wakeup_32_vector - wakeup_code) + + .balign 4 +wakeup_32_vector: + .long wakeup_32 - __START_KERNEL_map + .word __KERNEL32_CS, 0 .code32 wakeup_32:
@@ -96,65 +100,50 @@ wakeup_32: jnc bogus_cpu movl %edx,%edi - movw $__KERNEL_DS, %ax - movw %ax, %ds - movw %ax, %es - movw %ax, %fs - movw %ax, %gs + movl $__KERNEL_DS, %eax + movl %eax, %ds - movw $__KERNEL_DS, %ax - movw %ax, %ss - - mov $(wakeup_stack - __START_KERNEL_map), %esp movl saved_magic - __START_KERNEL_map, %eax cmpl $0x9abcdef0, %eax jne bogus_32_magic + movw $0x0e00 + 'i', %ds:(0xb8012) + movb $0xa8, %al ; outb %al, $0x80; + /* * Prepare for entering 64bits mode */ - /* Enable PAE mode and PGE */ + /* Enable PAE */ xorl %eax, %eax btsl $5, %eax - btsl $7, %eax movl %eax, %cr4 /* Setup early boot stage 4 level pagetables */ movl $(wakeup_level4_pgt - __START_KERNEL_map), %eax movl %eax, %cr3 - /* Setup EFER (Extended Feature Enable Register) */ - movl $MSR_EFER, %ecx - rdmsr - /* Fool rdmsr and reset %eax to avoid dependences */ - xorl %eax, %eax /* Enable Long Mode */ + xorl %eax, %eax btsl $_EFER_LME, %eax - /* Enable System Call */ - btsl $_EFER_SCE, %eax - /* No Execute supported? */ + /* No Execute supported? */ btl $20,%edi jnc 1f btsl $_EFER_NX, %eax -1: /* Make changes effective */ +1: movl $MSR_EFER, %ecx + xorl %edx, %edx wrmsr - wbinvd xorl %eax, %eax btsl $31, %eax /* Enable paging and in turn activate Long Mode */ btsl $0, %eax /* Enable protected mode */ - btsl $1, %eax /* Enable MP */ - btsl $4, %eax /* Enable ET */ - btsl $5, %eax /* Enable NE */ - btsl $16, %eax /* Enable WP */ - btsl $18, %eax /* Enable AM */ /* Make changes effective */ movl %eax, %cr0 + /* At this point: CR4.PAE must be 1 CS.L must be 0
@@ -162,11 +151,6 @@ wakeup_32: Next instruction must be a branch This must be on identity-mapped page */ - jmp reach_compatibility_mode -reach_compatibility_mode: - movw $0x0e00 + 'i', %ds:(0xb8012) - movb $0xa8, %al ; outb %al, $0x80; - /* * At this point we're in long mode but in 32bit compatibility mode * with EFER.LME = 1, CS.L = 0, CS.D = 1 (and in turn
@@ -174,24 +158,19 @@ reach_compatibility_mode: * the new gdt/idt that has __KERNEL_CS with CS.L = 1. */ - movw $0x0e00 + 'n', %ds:(0xb8014) - movb $0xa9, %al ; outb %al, $0x80 - - /* Load new GDT with the 64bit segment using 32bit descriptor */ - movl $(pGDT32 - __START_KERNEL_map), %eax - lgdt (%eax) - - movl $(wakeup_jumpvector - __START_KERNEL_map), %eax /* Finally jump in 64bit mode */ - ljmp *(%eax) + ljmp *(wakeup_long64_vector - __START_KERNEL_map) -wakeup_jumpvector: - .long wakeup_long64 - __START_KERNEL_map - .word __KERNEL_CS + .balign 4 +wakeup_long64_vector: + .long wakeup_long64 - __START_KERNEL_map + .word __KERNEL_CS, 0 .code64 - /* Hooray, we are in Long 64-bit mode (but still running in low memory) */ + /* Hooray, we are in Long 64-bit mode (but still running in + * low memory) + */ wakeup_long64: /* * We must switch to a new descriptor in kernel space for the GDT
@@ -201,6 +180,9 @@ wakeup_long64: */ lgdt cpu_gdt_descr - __START_KERNEL_map + movw $0x0e00 + 'n', %ds:(0xb8014) + movb $0xa9, %al ; outb %al, $0x80 + movw $0x0e00 + 'u', %ds:(0xb8016) nop
@@ -227,33 +209,19 @@ wakeup_long64: .align 64 gdta: + /* Its good to keep gdt in sync with one in trampoline.S */ .word 0, 0, 0, 0 # dummy - - .word 0, 0, 0, 0 # unused - - .word 0xFFFF # 4Gb - (0x100000*0x1000 = 4Gb) - .word 0 # base address = 0 - .word 0x9B00 # code read/exec. ??? Why I need 0x9B00 (as opposed to 0x9A00 in order for this to work?) - .word 0x00CF # granularity = 4096, 386 - # (+5th nibble of limit) - - .word 0xFFFF # 4Gb - (0x100000*0x1000 = 4Gb) - .word 0 # base address = 0 - .word 0x9200 # data read/write - .word 0x00CF # granularity = 4096, 386 - # (+5th nibble of limit) -# this is 64bit descriptor for code - .word 0xFFFF - .word 0 - .word 0x9A00 # code read/exec - .word 0x00AF # as above, but it is long mode and with D=0 + /* ??? Why I need the accessed bit set in order for this to work? */ + .quad 0x00cf9b000000ffff # __KERNEL32_CS + .quad 0x00af9b000000ffff # __KERNEL_CS + .quad 0x00cf93000000ffff # __KERNEL_DS idt_48a: .word 0 # idt limit = 0 .word 0, 0 # idt base = 0L gdt_48a: - .word 0x8000 # gdt limit=2048, + .word 0x800 # gdt limit=2048, # 256 GDT entries .word 0, 0 # gdt base (filled in later)
@@ -263,7 +231,7 @@ video_mode: .quad 0 video_flags: .quad 0 bogus_real_magic: - movb $0xba,%al ; outb %al,$0x80 + movb $0xba,%al ; outb %al,$0x80 jmp bogus_real_magic bogus_32_magic:
_
Re: [PATCH 11/20] x86_64: wakeup.S misc cleanups
Hi!
Quoted 20 lines
o Various cleanups. One of the main purpose of cleanups is that make
wakeup.Sas close as possible totrampoline.S.o Following are the changes
- Indentations for comments.
- Changed the gdt table to compact form and to resemble the one intrampoline.S
- Take the jump to 32bit from real mode using ljmpl. Makes code more readable.
- After enabling long mode, directly take a long jump for 64bit mode. No need to take an extra jump to "reach_comaptibility_mode"
- Stack is not used after real mode. So don't load stack in 32 bit mode.
- No need to enable PGE here.
- No need to do extra EFER read, anyway we trash the read contents.
- No need to enable system call (EFER_SCE). Anyway it will be enabled when original EFER is restored.
- No need to set MP, ET, NE, WP, AM bits in cr0. Very soon we will reload the original cr0 while restroing the processor state.
Quoted 2 lines
Signed-off-by Eric W. Biederman <[email protected]>Signed-off-by Vivek Goyal <[email protected]>
ACK, provided it was tested.
Pavel
Signature · 2 lines
(english) http://www.livejournal.com/~pavelmachek (cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
Re: [PATCH 11/20] x86_64: wakeup.S misc cleanups
Quoted 22 lines · Pavel Machek
Hi!
Quoted 20 lines
o Various cleanups. One of the main purpose of cleanups is that make
wakeup.Sas close as possible totrampoline.S.o Following are the changes
- Indentations for comments.
- Changed the gdt table to compact form and to resemble the one intrampoline.S
- Take the jump to 32bit from real mode using ljmpl. Makes code more readable.
- After enabling long mode, directly take a long jump for 64bit mode. No need to take an extra jump to "reach_comaptibility_mode"
- Stack is not used after real mode. So don't load stack in 32 bit mode.
- No need to enable PGE here.
- No need to do extra EFER read, anyway we trash the read contents.
- No need to enable system call (EFER_SCE). Anyway it will be enabled when original EFER is restored.
- No need to set MP, ET, NE, WP, AM bits in cr0. Very soon we will reload the original cr0 while restroing the processor state.
Quoted 5 lines
Quoted 2 lines
Signed-off-by Eric W. Biederman <[email protected]>Signed-off-by Vivek Goyal <[email protected]>ACK, provided it was tested.
Pavel
Hi Pavel,
Thanks. I tested all the S3 related changes during my last posting. That time I had access to an x86_64 box which supported ACPI state S3. Since then this code has not changed and it has been running successfully in RHEL5 kernels. Now I don't have access to an x86_64 machine which supports S3 so I can't test suspend to RAM. But I am sure that these patches are working as nothing has changed since last posting.
Just now Nigel reported successful suspend to RAM results for 2.6.20. I have requested him to test it for 2.6.21-rc2 also, if possible.
I have throughly tested suspend to disk (S4) and it works fine.
Thanks
Vivek
Re: [PATCH 11/20] x86_64: wakeup.S misc cleanups
In reply to Vivek GoyalHi!
arch/x86_64/kernel/acpi/wakeup.S wakeup_32:
Quoted 6 lines
arch/x86_64/kernel/acpi/wakeup.S renamed from arch/x86_64/kernel/acpi/wakeup.S~x86_64-wakeup.S-misc-cleanups +3
-2+ movw $0x0e00 + 'i', %ds:(0xb8012) + movb $0xa8, %al ; outb %al, $0x80; + - movw $0x0e00 + 'i', %ds:(0xb8012) - movb $0xa8, %al ; outb %al, $0x80;
Outbs were my debugging hacks, perhaps you can simply remove them at this point? Not sure how useful "Linux" debug print is, it can probably be removed, too.
Signature · 2 lines
(english) http://www.livejournal.com/~pavelmachek (cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
Re: [PATCH 11/20] x86_64: wakeup.S misc cleanups
Quoted 6 lines · Pavel Machek
Hi!
Quoted 3 lines
arch/x86_64/kernel/acpi/wakeup.S renamed from arch/x86_64/kernel/acpi/wakeup.S~x86_64-wakeup.S-misc-cleanups +3
-0+ movw $0x0e00 + 'i', %ds:(0xb8012) + movb $0xa8, %al ; outb %al, $0x80; +
Quoted 7 lines
arch/x86_64/kernel/acpi/wakeup.S wakeup_32: · line 168
Quoted 2 lines
arch/x86_64/kernel/acpi/wakeup.S renamed from arch/x86_64/kernel/acpi/wakeup.S~x86_64-wakeup.S-misc-cleanups +0
-2- movw $0x0e00 + 'i', %ds:(0xb8012) - movb $0xa8, %al ; outb %al, $0x80;Outbs were my debugging hacks, perhaps you can simply remove them at this point? Not sure how useful "Linux" debug print is, it can probably be removed, too.
Hi Pavel,
I found these debugging hacks useful while debugging some problem with my changes in this code. It helps to find out till what poing code flow as reached in this assembly code. So I think its not a bad idea to let this piece code be there.
Thanks
Vivek
Re: [PATCH 11/20] x86_64: wakeup.S misc cleanups
Hi!
Quoted 12 lines
Quoted 11 lines
arch/x86_64/kernel/acpi/wakeup.S wakeup_32:
Quoted 6 lines
arch/x86_64/kernel/acpi/wakeup.S renamed from arch/x86_64/kernel/acpi/wakeup.S~x86_64-wakeup.S-misc-cleanups +3
-2+ movw $0x0e00 + 'i', %ds:(0xb8012) + movb $0xa8, %al ; outb %al, $0x80; + - movw $0x0e00 + 'i', %ds:(0xb8012) - movb $0xa8, %al ; outb %al, $0x80;Outbs were my debugging hacks, perhaps you can simply remove them at this point? Not sure how useful "Linux" debug print is, it can probably be removed, too.
Quoted 6 lines
Hi Pavel,
I found these debugging hacks useful while debugging some problem with my changes in this code. It helps to find out till what poing code flow as reached in this assembly code. So I think its not a bad idea to let this piece code be there.
Ok. (I was not sure how common are displays of port 0x80).
Signature · 2 lines
(english) http://www.livejournal.com/~pavelmachek (cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
Re: [Fastboot] [PATCH 11/20] x86_64: wakeup.S misc cleanups
Quoted 11 lines · Pavel Machek
Quoted 11 lines
Quoted 11 lines
arch/x86_64/kernel/acpi/wakeup.S wakeup_32:
Quoted 6 lines
arch/x86_64/kernel/acpi/wakeup.S renamed from arch/x86_64/kernel/acpi/wakeup.S~x86_64-wakeup.S-misc-cleanups +3
-2+ movw $0x0e00 + 'i', %ds:(0xb8012) + movb $0xa8, %al ; outb %al, $0x80; + - movw $0x0e00 + 'i', %ds:(0xb8012) - movb $0xa8, %al ; outb %al, $0x80;Outbs were my debugging hacks, perhaps you can simply remove them at this point? Not sure how useful "Linux" debug print is, it can probably be removed, too.
Quoted 6 lines
Quoted 4 lines
I found these debugging hacks useful while debugging some problem with my changes in this code. It helps to find out till what poing code flow as reached in this assembly code. So I think its not a bad idea to let this piece code be there.
Ok. (I was not sure how common are displays of port
0x80).
They're now typically available in reasonably well stocked stores; I picked one up from CompUSA about a year ago...
Signature · 2 lines
David N. Lombard, Intel, Irvine, CA I do not speak for Intel Corporation; all comments are strictly my own.
PATCH 12/20 x86_64: 64bit ACPI wakeup trampoline
In reply to Vivek Goyalo Moved wakeup_level4_pgt into the wakeup routine so we can run the kernel above 4G.
o Now we first go to 64bit mode and continue to run from trampoline and then then start accessing kernel symbols and restore processor context. This enables us to resume even in relocatable kernel context when kernel might not be loaded at physical addr it has been compiled for.
o Removed the need for modifying any existing kernel page table.
o Increased the size of the wakeup routine to 8K. This is required as wake page tables are on trampoline itself and they got to be at 4K boundary, hence one page is not sufficient.
---
arch/x86_64/kernel/acpi/sleep.c | 22 ++------------ arch/x86_64/kernel/acpi/wakeup.S | 59 ++++++++++++++++++++++++--------------- arch/x86_64/kernel/head.S | 9 ----- 3 files changed, 41 insertions(+), 49 deletions(-)
arch/x86_64/kernel/acpi/sleep.c renamed from arch/x86_64/kernel/acpi/sleep.c~x86_64-64bit-ACPI-wakeup-trampoline +4 -18
@@ -60,17 +60,6 @@ extern char wakeup_start, wakeup_end;extern unsigned long acpi_copy_wakeup_routine (unsigned long ); -static pgd_t low_ptr; - -static void init_low_mapping (void ) -{ -pgd_t *slot0 =pgd_offset (current->mm,0UL ); - low_ptr = *slot0; -set_pgd (slot0, *pgd_offset (current->mm,PAGE_OFFSET )); -WARN_ON (num_online_cpus () !=1 ); -local_flush_tlb (); -} -/** * acpi_save_state_mem - save kernel state *
@@ -79,8 +68,6 @@ static void init_low_mapping(void)*/ int acpi_save_state_mem (void ) { -init_low_mapping (); -memcpy ((void *)acpi_wakeup_address, &wakeup_start, &wakeup_end - &wakeup_start);acpi_copy_wakeup_routine (acpi_wakeup_address);
@@ -93,8 +80,6 @@ int acpi_save_state_mem(void)*/ void acpi_restore_state_mem (void ) { -set_pgd (pgd_offset (current->mm,0UL ), low_ptr); -local_flush_tlb (); }/**
@@ -107,10 +92,11 @@ void acpi_restore_state_mem(void)*/ void __init acpi_reserve_bootmem (void ) { - acpi_wakeup_address = (unsigned long )alloc_bootmem_low (PAGE_SIZE ); -if ((&wakeup_end - &wakeup_start) >PAGE_SIZE ) + acpi_wakeup_address = (unsigned long )alloc_bootmem_low (PAGE_SIZE *2 ); +if ((&wakeup_end - &wakeup_start) > (PAGE_SIZE *2 ))printk (KERN_CRIT -"ACPI: Wakeup code way too big, will crash on attempt to suspend\n" ); +"ACPI: Wakeup code way too big, will crash on attempt" +" to suspend\n" ); }static int __init acpi_sleep_setup (char *str)
arch/x86_64/kernel/acpi/wakeup.S renamed from arch/x86_64/kernel/acpi/wakeup.S~x86_64-64bit-ACPI-wakeup-trampoline +37 -22
142 lines not on this page · raw message
arch/x86_64/kernel/head.S renamed from arch/x86_64/kernel/head.S~x86_64-64bit-ACPI-wakeup-trampoline +0 -9
@@ -308,15 +308,6 @@ NEXT_PAGE(level2_kernel_pgt) .data -#ifdef CONFIG_ACPI_SLEEP - .align PAGE_SIZE -ENTRY(wakeup_level4_pgt) - .quad level3_ident_pgt - __START_KERNEL_map + _KERNPG_TABLE - .fill 510,8,0 - /* (2^48-(2*1024*1024*1024))/(2^39) = 511 */ - .quad level3_kernel_pgt - __START_KERNEL_map + _KERNPG_TABLE -#endif - #ifndef CONFIG_HOTPLUG_CPU __INITDATA #endif
_
Re: [PATCH 12/20] x86_64: 64bit ACPI wakeup trampoline
Hi!
Quoted 17 lines
o Moved
wakeup_level4_pgtinto the wakeup routine so we can run the kernel above 4G.o Now we first go to 64bit mode and continue to run from trampoline and then then start accessing kernel symbols and restore processor context. This enables us to resume even in relocatable kernel context when kernel might not be loaded at physical addr it has been compiled for.
o Removed the need for modifying any existing kernel page table.
o Increased the size of the wakeup routine to 8K. This is required as wake page tables are on trampoline itself and they got to be at 4K boundary, hence one page is not sufficient.
Signed-off-by Eric W. Biederman <[email protected]>Signed-off-by Vivek Goyal <[email protected]>
arch/x86_64/kernel/acpi/sleep.c void acpi_restore_state_mem(void) · line 99
Quoted 5 lines
arch/x86_64/kernel/acpi/sleep.c renamed from arch/x86_64/kernel/acpi/sleep.c~x86_64-64bit-ACPI-wakeup-trampoline +3
-1+if ((&wakeup_end - &wakeup_start) > (PAGE_SIZE *2 ))printk (KERN_CRIT -"ACPI: Wakeup code way too big, will crash on attempt to suspend\n" ); +"ACPI: Wakeup code way too big, will crash on attempt" +" to suspend\n" );
Hmm, if you split it like
printk(KERN_CRIT "ACPI: Wakeup code way too big, will crash" "on attempt to suspend\n");
...you'll still keep 80-column rule while keeping it readable.
arch/x86_64/kernel/acpi/wakeup.S wakeup_32: · line 162
Quoted 6 lines
arch/x86_64/kernel/acpi/wakeup.S renamed from arch/x86_64/kernel/acpi/wakeup.S~x86_64-64bit-ACPI-wakeup-trampoline +1
-1@@ -159,11 +159,11 @@ wakeup_32: */ /* Finally jump in 64bit mode */ - ljmp *(wakeup_long64_vector - __START_KERNEL_map) + ljmp *(wakeup_long64_vector - wakeup_code)(%esi)
spaces vs. tabs problem.
Otherwise looks good. ACK if it was tested.
Pavel
Signature · 2 lines
(english) http://www.livejournal.com/~pavelmachek (cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
Re: [Fastboot] [PATCH 12/20] x86_64: 64bit ACPI wakeup trampoline
Quoted 8 lines · Pavel Machek
arch/x86_64/kernel/acpi/sleep.c void acpi_restore_state_mem(void) · line 99
Quoted 6 lines
arch/x86_64/kernel/acpi/sleep.c renamed from arch/x86_64/kernel/acpi/sleep.c~x86_64-64bit-ACPI-wakeup-trampoline +3
-1+if ((&wakeup_end - &wakeup_start) > (PAGE_SIZE *2 ))printk (KERN_CRIT -"ACPI: Wakeup code way too big, will crash on attempt to suspend\n" ); +"ACPI: Wakeup code way too big, will crash on attempt" +" to suspend\n" );Hmm, if you split it like
Quoted 4 lines
printk(KERN_CRIT "ACPI: Wakeup code way too big, will crash" "on attempt to suspend\n");...you'll still keep 80-column rule while keeping it readable.
But I guess with a space after "crash" or before "on" :)
Regards,
Bernhard
Re: [PATCH 12/20] x86_64: 64bit ACPI wakeup trampoline
In reply to Pavel MachekOn Wed, Mar 07, 2007 at 11:45:08PM +0100, Pavel Machek wrote:
[..]
Quoted 8 lines
Review
Quoted 6 lines
(quoted diff) +3
-1+ if ((&wakeup_end - &wakeup_start) > (PAGE_SIZE*2)) printk(KERN_CRIT - "ACPI: Wakeup code way too big, will crash on attempt to suspend\n"); + "ACPI: Wakeup code way too big, will crash on attempt" + " to suspend\n");Hmm, if you split it like
Quoted 5 lines
printk(KERN_CRIT "ACPI: Wakeup code way too big, will crash" "on attempt to suspend\n");...you'll still keep 80-column rule while keeping it readable.
Thanks. Done the changes in attached patch.
Quoted 9 lines
Review wakeup_32: · line 162
Quoted 6 lines
(quoted diff) +1
-1@@ -159,11 +159,11 @@ wakeup_32: */ /* Finally jump in 64bit mode */ - ljmp *(wakeup_long64_vector - __START_KERNEL_map) + ljmp *(wakeup_long64_vector - wakeup_code)(%esi)spaces vs. tabs problem.
Thanks. Done the changes in attached patch.
Vivek
o Moved wakeup_level4_pgt into the wakeup routine so we can run the kernel above 4G.
o Now we first go to 64bit mode and continue to run from trampoline and then then start accessing kernel symbols and restore processor context. This enables us to resume even in relocatable kernel context when kernel might not be loaded at physical addr it has been compiled for.
o Removed the need for modifying any existing kernel page table.
o Increased the size of the wakeup routine to 8K. This is required as wake page tables are on trampoline itself and they got to be at 4K boundary, hence one page is not sufficient.
---
arch/x86_64/kernel/acpi/sleep.c | 23 ++------------- arch/x86_64/kernel/acpi/wakeup.S | 59 ++++++++++++++++++++++++--------------- arch/x86_64/kernel/head.S | 9 ----- 3 files changed, 41 insertions(+), 50 deletions(-)
arch/x86_64/kernel/acpi/sleep.c renamed from arch/x86_64/kernel/acpi/sleep.c~x86_64-64bit-ACPI-wakeup-trampoline +4 -19
@@ -60,17 +60,6 @@ extern char wakeup_start, wakeup_end;extern unsigned long acpi_copy_wakeup_routine (unsigned long ); -static pgd_t low_ptr; - -static void init_low_mapping (void ) -{ -pgd_t *slot0 =pgd_offset (current->mm,0UL ); - low_ptr = *slot0; -set_pgd (slot0, *pgd_offset (current->mm,PAGE_OFFSET )); -WARN_ON (num_online_cpus () !=1 ); -local_flush_tlb (); -} -/** * acpi_save_state_mem - save kernel state *
@@ -79,8 +68,6 @@ static void init_low_mapping(void)*/ int acpi_save_state_mem (void ) { -init_low_mapping (); -memcpy ((void *)acpi_wakeup_address, &wakeup_start, &wakeup_end - &wakeup_start);acpi_copy_wakeup_routine (acpi_wakeup_address);
@@ -93,8 +80,6 @@ int acpi_save_state_mem(void)*/ void acpi_restore_state_mem (void ) { -set_pgd (pgd_offset (current->mm,0UL ), low_ptr); -local_flush_tlb (); }/**
@@ -107,10 +92,10 @@ void acpi_restore_state_mem(void)*/ void __init acpi_reserve_bootmem (void ) { - acpi_wakeup_address = (unsigned long )alloc_bootmem_low (PAGE_SIZE ); -if ((&wakeup_end - &wakeup_start) >PAGE_SIZE ) -printk (KERN_CRIT -"ACPI: Wakeup code way too big, will crash on attempt to suspend\n" ); + acpi_wakeup_address = (unsigned long )alloc_bootmem_low (PAGE_SIZE *2 ); +if ((&wakeup_end - &wakeup_start) > (PAGE_SIZE *2 )) +printk (KERN_CRIT "ACPI: Wakeup code way too big, will crash" +" on attempt to suspend\n" ); }static int __init acpi_sleep_setup (char *str)
arch/x86_64/kernel/acpi/wakeup.S renamed from arch/x86_64/kernel/acpi/wakeup.S~x86_64-64bit-ACPI-wakeup-trampoline +37 -22
142 lines not on this page · raw message
arch/x86_64/kernel/head.S renamed from arch/x86_64/kernel/head.S~x86_64-64bit-ACPI-wakeup-trampoline +0 -9
@@ -308,15 +308,6 @@ NEXT_PAGE(level2_kernel_pgt) .data -#ifdef CONFIG_ACPI_SLEEP - .align PAGE_SIZE -ENTRY(wakeup_level4_pgt) - .quad level3_ident_pgt - __START_KERNEL_map + _KERNPG_TABLE - .fill 510,8,0 - /* (2^48-(2*1024*1024*1024))/(2^39) = 511 */ - .quad level3_kernel_pgt - __START_KERNEL_map + _KERNPG_TABLE -#endif - #ifndef CONFIG_HOTPLUG_CPU __INITDATA #endif
_
Re: [PATCH 12/20] x86_64: 64bit ACPI wakeup trampoline
Hi!
Quoted 16 lines
Quoted 2 lines
...you'll still keep 80-column rule while keeping it readable.
Thanks. Done the changes in attached patch.
Quoted 9 lines
arch/x86_64/kernel/acpi/wakeup.S wakeup_32: · line 162
Quoted 6 lines
arch/x86_64/kernel/acpi/wakeup.S renamed from arch/x86_64/kernel/acpi/wakeup.S~x86_64-64bit-ACPI-wakeup-trampoline +1
-1@@ -159,11 +159,11 @@ wakeup_32: */ /* Finally jump in 64bit mode */ - ljmp *(wakeup_long64_vector - __START_KERNEL_map) + ljmp *(wakeup_long64_vector - wakeup_code)(%esi)spaces vs. tabs problem.
Thanks. Done the changes in attached patch.
...
Quoted 6 lines
o Increased the size of the wakeup routine to 8K. This is required as wake page tables are on trampoline itself and they got to be at 4K boundary, hence one page is not sufficient.
Signed-off-by Eric W. Biederman <[email protected]>Signed-off-by Vivek Goyal <[email protected]>
ACK.
Pavel
Signature · 2 lines
(english) http://www.livejournal.com/~pavelmachek (cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
PATCH 13/20 x86_64: Modify discover_ebda to use virtual addresses
In reply to Vivek Goyal---
arch/x86_64/kernel/setup.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
arch/x86_64/kernel/setup.c renamed from arch/x86_64/kernel/setup.c~x86_64-Modify-discover_ebda-to-use-virtual-addresses +2 -2
@@ -205,10 +205,10 @@ 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 = *(unsigned short *)__va (EBDA_ADDR_POINTER ); ebda_addr <<=4 ; - ebda_size = *(unsigned short *)(unsigned long )ebda_addr; + ebda_size = *(unsigned short *)__va (ebda_addr);/* Round EBDA up to pages */ if (ebda_size ==0 )
_
PATCH 14/20 x86_64: Remove the identity mapping as early as possible
In reply to Vivek GoyalWith the rewrite of the SMP trampoline and the early page allocator there is nothing that needs identity mapped pages, once we start executing C code.
So add zap_identity_mappings into head64.c and remove zap_low_mappings() from much later in the code. The functions
are subtly different thus the name change.
This also kills boot_level4_pgt which was from an earlier attempt to move the identity mappings as early as possible, and is now no longer needed. Essentially I have replaced boot_level4_pgt with trampoline_level4_pgt in trampoline.S
---
arch/x86_64/kernel/head.S | 39 ++++++++++++++------------------------- arch/x86_64/kernel/head64.c | 17 +++++++++++------ arch/x86_64/kernel/setup.c | 2 -- arch/x86_64/kernel/setup64.c | 1 - arch/x86_64/mm/init.c | 24 ------------------------ include/asm-x86_64/pgtable.h | 1 - include/asm-x86_64/proto.h | 2 -- 7 files changed, 25 insertions(+), 61 deletions(-)
arch/x86_64/kernel/head64.c renamed from arch/x86_64/kernel/head64.c~x86_64-Remove-the-identity-mapping-as-early-as-possible +11 -6
@@ -18,8 +18,16 @@#include <asm/setup.h> #include <asm/desc.h> #include <asm/pgtable.h> +#include <asm/tlbflush.h> #include <asm/sections.h> +static void __init zap_identity_mappings (void ) +{ +pgd_t *pgd =pgd_offset_k (0UL ); +pgd_clear (pgd); +__flush_tlb (); +} +/* Don't add a printk in there. printk relies on the PDA which is not initialized yet. */ static void __init clear_bss (void )
@@ -57,18 +65,15 @@ void __init x86_64_start_kernel(char * r/* clear bss before set_intr_gate with early_idt_handler */ clear_bss (); +/* Make NULL pointers segfault */ +zap_identity_mappings (); +for (i =0 ; i <IDT_ENTRIES ; i++)set_intr_gate (i, early_idt_handler); asmvolatile ("lidt %0" ::"m" (idt_descr));early_printk ("Kernel alive\n" ); -/* -* 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))); -for (i =0 ; i <NR_CPUS ; i++)cpu_pda (i) = &boot_cpu_pda[i];
arch/x86_64/kernel/head.S renamed from arch/x86_64/kernel/head.S~x86_64-Remove-the-identity-mapping-as-early-as-possible +14 -25
@@ -71,7 +71,7 @@ startup_32: movl %eax, %cr4 /* Setup early boot stage 4 level pagetables */ - movl $(boot_level4_pgt - __START_KERNEL_map), %eax + movl $(init_level4_pgt - __START_KERNEL_map), %eax movl %eax, %cr3 /* Setup EFER (Extended Feature Enable Register) */
@@ -115,7 +115,7 @@ ENTRY(secondary_startup_64) movq %rax, %cr4 /* Setup early boot stage 4 level pagetables. */ - movq $(boot_level4_pgt - __START_KERNEL_map), %rax + movq $(init_level4_pgt - __START_KERNEL_map), %rax movq %rax, %cr3 /* Check if nx is implemented */
@@ -274,9 +274,19 @@ ENTRY(name) i = i + 1 ; \ .endr + /* + * This default setting generates an ident mapping at address 0x100000 + * and a mapping for the kernel that precisely maps virtual address + * 0xffffffff80000000 to physical address 0x000000. (always using + * 2Mbyte large pages provided by PAE mode) + */ NEXT_PAGE(init_level4_pgt) - /* This gets initialized in x86_64_start_kernel */ - .fill 512,8,0 + .quad level3_ident_pgt - __START_KERNEL_map + _KERNPG_TABLE + .fill 257,8,0 + .quad level3_ident_pgt - __START_KERNEL_map + _KERNPG_TABLE + .fill 252,8,0 + /* (2^48-(2*1024*1024*1024))/(2^39) = 511 */ + .quad level3_kernel_pgt - __START_KERNEL_map + _PAGE_TABLE NEXT_PAGE(level3_ident_pgt) .quad level2_ident_pgt - __START_KERNEL_map + _KERNPG_TABLE
@@ -307,27 +317,6 @@ NEXT_PAGE(level2_kernel_pgt) #undef NEXT_PAGE .data - -#ifndef CONFIG_HOTPLUG_CPU - __INITDATA -#endif - /* - * This default setting generates an ident mapping at address 0x100000 - * and a mapping for the kernel that precisely maps virtual address - * 0xffffffff80000000 to physical address 0x000000. (always using - * 2Mbyte large pages provided by PAE mode) - */ - .align PAGE_SIZE -ENTRY(boot_level4_pgt) - .quad level3_ident_pgt - __START_KERNEL_map + _KERNPG_TABLE - .fill 257,8,0 - .quad level3_ident_pgt - __START_KERNEL_map + _KERNPG_TABLE - .fill 252,8,0 - /* (2^48-(2*1024*1024*1024))/(2^39) = 511 */ - .quad level3_kernel_pgt - __START_KERNEL_map + _PAGE_TABLE - - .data - .align 16 .globl cpu_gdt_descr cpu_gdt_descr:
arch/x86_64/kernel/setup64.c renamed from arch/x86_64/kernel/setup64.c~x86_64-Remove-the-identity-mapping-as-early-as-possible +0 -1
@@ -201,7 +201,6 @@ void __cpuinit cpu_init (void)/* CPU 0 is initialised in head64.c */ if (cpu !=0 ) {pda_init (cpu); -zap_low_mappings (cpu); }else estacks = boot_exception_stacks;
arch/x86_64/kernel/setup.c renamed from arch/x86_64/kernel/setup.c~x86_64-Remove-the-identity-mapping-as-early-as-possible +0 -2
@@ -274,8 +274,6 @@ void __init setup_arch(char **cmdline_p)dmi_scan_machine (); -zap_low_mappings (0 ); -#ifdef CONFIG_ACPI /* * Initialize the ACPI boot-time table parser (gets the RSDP and SDT).
arch/x86_64/mm/init.c renamed from arch/x86_64/mm/init.c~x86_64-Remove-the-identity-mapping-as-early-as-possible +0 -24
@@ -378,21 +378,6 @@ void __meminit init_memory_mapping(unsig__flush_tlb_all (); } -void __cpuinit zap_low_mappings (int cpu) -{ -if (cpu ==0 ) { -pgd_t *pgd =pgd_offset_k (0UL ); -pgd_clear (pgd); - }else { -/* -* 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))); - } -__flush_tlb_all (); -} -#ifndef CONFIG_NUMA void __init paging_init (void ) {
@@ -569,15 +554,6 @@ void __init mem_init(void) reservedpages << (PAGE_SHIFT -10 ), datasize >>10 , initsize >> 10); - -#ifdef CONFIG_SMP -/* -* Sync boot_level4_pgt mappings with the init_level4_pgt -* except for the low identity mappings which are already zapped -* in init_level4_pgt. This sync-up is essential for AP's bringup -*/ -memcpy (boot_level4_pgt+1 , init_level4_pgt+1 , (PTRS_PER_PGD -1 )*sizeof (pgd_t)); -#endif }void free_init_pages (char *what,unsigned long begin,unsigned long end)
include/asm-x86_64/pgtable.h renamed from include/asm-x86_64/pgtable.h~x86_64-Remove-the-identity-mapping-as-early-as-possible +0 -1
@@ -18,7 +18,6 @@ extern pud_t level3_kernel_pgt[512];extern pud_t level3_ident_pgt[512 ];extern pmd_t level2_kernel_pgt[512 ];extern pgd_t init_level4_pgt[]; -extern pgd_t boot_level4_pgt[];extern unsigned long __supported_pte_mask;#define swapper_pg_dir init_level4_pgt
include/asm-x86_64/proto.h renamed from include/asm-x86_64/proto.h~x86_64-Remove-the-identity-mapping-as-early-as-possible +0 -2
@@ -11,8 +11,6 @@ struct pt_regs;extern void start_kernel (void );extern void pda_init (int ); -extern void zap_low_mappings (int cpu); -extern void early_idt_handler (void );extern void mcheck_init (struct cpuinfo_x86 *c);
_
PATCH 15/20 Move swsusp __pa() dependent code to arch portion
In reply to Vivek Goyalo __pa() should be used only on kernel linearly mapped virtual addresses and not on kernel text and data addresses.
o Hibernation code needs to determine the physical address associated with kernel symbol to mark a section boundary which contains pages which don't have to be saved and restored during hibernate/resume operation.
o Move this piece of code in arch dependent section. So that architectures which don't have kernel text/data mapped into kernel linearly mapped region can come up with their own ways of determining physical addresses associated with a kernel text.
---
arch/i386/power/suspend.c | 14 ++++++++++++++ arch/powerpc/kernel/Makefile | 1 + arch/powerpc/kernel/suspend.c | 24 ++++++++++++++++++++++++ arch/x86_64/kernel/suspend.c | 14 ++++++++++++++ kernel/power/power.h | 5 ++--- kernel/power/snapshot.c | 11 ----------- 6 files changed, 55 insertions(+), 14 deletions(-)
arch/i386/power/suspend.c renamed from arch/i386/power/suspend.c~move-swsusp-__pa-dependent-code-to-arch-portion +14 -0
@@ -16,6 +16,9 @@/* Defined in arch/i386/power/swsusp.S */ extern int restore_image (void ); +/* References to section boundaries */ +extern const void __nosave_begin, __nosave_end; +/* Pointer to the temporary resume page tables */ pgd_t *resume_pg_dir;
@@ -156,3 +159,14 @@ int swsusp_arch_resume(void)restore_image ();return 0 ; } + +/* +* pfn_is_nosave - check if given pfn is in the 'nosave' section +*/ + +int pfn_is_nosave (unsigned long pfn) +{ +unsigned long nosave_begin_pfn =__pa_symbol (&__nosave_begin) >>PAGE_SHIFT ; +unsigned long nosave_end_pfn =PAGE_ALIGN (__pa_symbol (&__nosave_end)) >>PAGE_SHIFT ; +return (pfn >= nosave_begin_pfn) && (pfn < nosave_end_pfn); +}
arch/powerpc/kernel/Makefile renamed from arch/powerpc/kernel/Makefile~move-swsusp-__pa-dependent-code-to-arch-portion +1 -0
@@ -37,6 +37,7 @@ obj-$(CONFIG_CRASH_DUMP) += crash_dump.o obj-$(CONFIG_6xx) += idle_6xx.o l2cr_6xx.o cpu_setup_6xx.o obj-$(CONFIG_TAU) += tau_6xx.o obj32-$(CONFIG_SOFTWARE_SUSPEND) += swsusp_32.o +obj-$(CONFIG_SOFTWARE_SUSPEND) += suspend.o obj32-$(CONFIG_MODULES) += module_32.o ifeq ($(CONFIG_PPC_MERGE),y)
arch/powerpc/kernel/suspend.c new file +24 -0
@@ -0,0 +1,24 @@ +/* +* Suspend support specific for power. +* +* Distribute under GPLv2 +* +* Copyright (c) 2002 Pavel Machek <[email protected]> +* Copyright (c) 2001 Patrick Mochel <[email protected]> +*/ + +#include <asm/page.h> + +/* References to section boundaries */ +extern const void __nosave_begin, __nosave_end; + +/* +* pfn_is_nosave - check if given pfn is in the 'nosave' section +*/ + +int pfn_is_nosave (unsigned long pfn) +{ +unsigned long nosave_begin_pfn =__pa (&__nosave_begin) >>PAGE_SHIFT ; +unsigned long nosave_end_pfn =PAGE_ALIGN (__pa (&__nosave_end)) >>PAGE_SHIFT ; +return (pfn >= nosave_begin_pfn) && (pfn < nosave_end_pfn); +}
arch/x86_64/kernel/suspend.c renamed from arch/x86_64/kernel/suspend.c~move-swsusp-__pa-dependent-code-to-arch-portion +14 -0
@@ -13,6 +13,9 @@#include <asm/page.h> #include <asm/pgtable.h> +/* References to section boundaries */ +extern const void __nosave_begin, __nosave_end; +struct saved_context saved_context;unsigned long saved_context_eax, saved_context_ebx, saved_context_ecx, saved_context_edx;
@@ -220,4 +223,15 @@ int swsusp_arch_resume(void)restore_image (); return 0; } + +/* +* pfn_is_nosave - check if given pfn is in the 'nosave' section +*/ + +int pfn_is_nosave (unsigned long pfn) +{ +unsigned long nosave_begin_pfn =__pa_symbol (&__nosave_begin) >>PAGE_SHIFT ; +unsigned long nosave_end_pfn =PAGE_ALIGN (__pa_symbol (&__nosave_end)) >>PAGE_SHIFT ; +return (pfn >= nosave_begin_pfn) && (pfn < nosave_end_pfn); +}#endif /* CONFIG_SOFTWARE_SUSPEND */
kernel/power/power.h renamed from kernel/power/power.h~move-swsusp-__pa-dependent-code-to-arch-portion +2 -3
@@ -23,6 +23,8 @@ static inline int pm_suspend_disk(void) }#endif +extern int pfn_is_nosave (unsigned long ); +extern struct mutex pm_mutex;#define power_attr (_name) \
@@ -37,9 +39,6 @@ static struct subsys_attribute _name##_aextern struct subsystem power_subsys; -/* References to section boundaries */ -extern const void __nosave_begin, __nosave_end; -/* Preferred image size in bytes (default 500 MB) */ extern unsigned long image_size;extern int in_suspend;
kernel/power/snapshot.c renamed from kernel/power/snapshot.c~move-swsusp-__pa-dependent-code-to-arch-portion +0 -11
@@ -651,17 +651,6 @@ static inline unsigned int count_highmem#endif /* CONFIG_HIGHMEM */ /** -* pfn_is_nosave - check if given pfn is in the 'nosave' section -*/ - -static inline int pfn_is_nosave (unsigned long pfn) -{ -unsigned long nosave_begin_pfn =__pa (&__nosave_begin) >>PAGE_SHIFT ; -unsigned long nosave_end_pfn =PAGE_ALIGN (__pa (&__nosave_end)) >>PAGE_SHIFT ; -return (pfn >= nosave_begin_pfn) && (pfn < nosave_end_pfn); -} - -/** * saveable - Determine whether a non-highmem page should be included in * the suspend image. *
_
Re: [PATCH 15/20] Move swsusp __pa() dependent code to arch portion
Hi!
Quoted 7 lines
o
__pa()should be used only on kernel linearly mapped virtual addresses and not on kernel text and data addresses.o Hibernation code needs to determine the physical address associated with kernel symbol to mark a section boundary which contains pages which don't have to be saved and restored during hibernate/resume operation.
Quoted 6 lines
o Move this piece of code in arch dependent section. So that architectures which don't have kernel text/data mapped into kernel linearly mapped region can come up with their own ways of determining physical addresses associated with a kernel text.
Signed-off-by Vivek Goyal <[email protected]>
...hmm, but that means 3 copies of same code. Can we put the
arch/i386/power/suspend.c int swsusp_arch_resume(void) · line 172
Quoted 10 lines
arch/i386/power/suspend.c renamed from arch/i386/power/suspend.c~move-swsusp-__pa-dependent-code-to-arch-portion +10
-0+/* +* pfn_is_nosave - check if given pfn is in the 'nosave' section +*/ + +int pfn_is_nosave (unsigned long pfn) +{ +unsigned long nosave_begin_pfn =__pa_symbol (&__nosave_begin) >>PAGE_SHIFT ; +unsigned long nosave_end_pfn =PAGE_ALIGN (__pa_symbol (&__nosave_end)) >>PAGE_SHIFT ; +return (pfn >= nosave_begin_pfn) && (pfn < nosave_end_pfn); +}
...in asm-generic/suspend.h (or something) and then just include it?
Pavel
Signature · 2 lines
(english) http://www.livejournal.com/~pavelmachek (cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
Re: [PATCH 15/20] Move swsusp __pa() dependent code to arch portion
Quoted 9 lines · Pavel Machek
Hi!
Quoted 7 lines
o
__pa()should be used only on kernel linearly mapped virtual addresses and not on kernel text and data addresses.o Hibernation code needs to determine the physical address associated with kernel symbol to mark a section boundary which contains pages which don't have to be saved and restored during hibernate/resume operation.
Quoted 9 lines
Quoted 6 lines
o Move this piece of code in arch dependent section. So that architectures which don't have kernel text/data mapped into kernel linearly mapped region can come up with their own ways of determining physical addresses associated with a kernel text.
Signed-off-by Vivek Goyal <[email protected]>...hmm, but that means 3 copies of same code. Can we put the
Actually it is not exactly same code. i386 and x86_64 use __pa_symbol() and powerpc uses __pa() for determining physical address associated with a kernel text symbol. That's the precise intent here. Leave it to arch code to decide how to calculate physical address associated with a kernel symbol.
Quoted 5 lines
Quoted 5 lines
arch/i386/power/suspend.c renamed from arch/i386/power/suspend.c~move-swsusp-__pa-dependent-code-to-arch-portion +5
-0+/* +* pfn_is_nosave - check if given pfn is in the 'nosave' section +*/ + +int pfn_is_nosave (unsigned long pfn)
Quoted 8 lines
arch/i386/power/suspend.c int swsusp_arch_resume(void) · line 172
Quoted 5 lines
arch/i386/power/suspend.c renamed from arch/i386/power/suspend.c~move-swsusp-__pa-dependent-code-to-arch-portion +5
-0+{ +unsigned long nosave_begin_pfn =__pa_symbol (&__nosave_begin) >>PAGE_SHIFT ; +unsigned long nosave_end_pfn =PAGE_ALIGN (__pa_symbol (&__nosave_end)) >>PAGE_SHIFT ; +return (pfn >= nosave_begin_pfn) && (pfn < nosave_end_pfn); +}...in
asm-generic/suspend.h(or something) and then just include it?
Pavel
As code is not exactly same, we can't put it in asm-generic/suspend.h.
Thanks
Vivek
Re: [PATCH 15/20] Move swsusp __pa() dependent code to arch portion
Hi!
Quoted 11 lines
Quoted 9 lines
arch/i386/power/suspend.c int swsusp_arch_resume(void) · line 172
Quoted 6 lines
arch/i386/power/suspend.c renamed from arch/i386/power/suspend.c~move-swsusp-__pa-dependent-code-to-arch-portion +6
-0+int pfn_is_nosave (unsigned long pfn) +{ +unsigned long nosave_begin_pfn =__pa_symbol (&__nosave_begin) >>PAGE_SHIFT ; +unsigned long nosave_end_pfn =PAGE_ALIGN (__pa_symbol (&__nosave_end)) >>PAGE_SHIFT ; +return (pfn >= nosave_begin_pfn) && (pfn < nosave_end_pfn); +}...in
asm-generic/suspend.h(or something) and then just include it?
PavelAs code is not exactly same, we can't put it in
asm-generic/suspend.h.
Ok... ACK on the original patch, then.
Pavel
Signature · 2 lines
(english) http://www.livejournal.com/~pavelmachek (cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
PATCH 16/20 swsusp: do not use virt_to_page on kernel data address
In reply to Vivek Goyalo virt_to_page() call should be used on kernel linear addresses and not on kernel text and data addresses. Swsusp code uses it on kernel data (statically allocated swsusp_header).
o Allocate swsusp_header dynamically so that virt_to_page() can be used safely.
o I am changing this because in next few patches, __pa() on x86_64 will no longer support kernel text and data addresses and hibernation breaks.
---
kernel/power/swap.c | 42 +++++++++++++++++++++++++++--------------- 1 file changed, 27 insertions(+), 15 deletions(-)
kernel/power/swap.c renamed from kernel/power/swap.c~swsusp-do-not-use-virt_to_page-on-kernel-data-addr +27 -15
@@ -33,12 +33,14 @@ extern char resume_file[];#define SWSUSP_SIG "S1SUSPEND" -static struct swsusp_header { +struct swsusp_header {char reserved[PAGE_SIZE -20 -sizeof (sector_t)];sector_t image;char orig_sig[10 ];char sig[10 ]; -} __attribute__((packed,aligned (PAGE_SIZE ))) swsusp_header; +} __attribute__((packed)); + +static struct swsusp_header *swsusp_header;/* * General things
@@ -141,14 +143,14 @@ static int mark_swapfiles(sector_t start {int error; -bio_read_page (swsusp_resume_block, &swsusp_header,NULL ); -if (!memcmp ("SWAP-SPACE" ,swsusp_header.sig,10 ) || - !memcmp ("SWAPSPACE2" ,swsusp_header.sig,10 )) { -memcpy (swsusp_header.orig_sig,swsusp_header.sig,10 ); -memcpy (swsusp_header.sig,SWSUSP_SIG ,10 ); - swsusp_header.image = start; +bio_read_page (swsusp_resume_block, swsusp_header,NULL ); +if (!memcmp ("SWAP-SPACE" ,swsusp_header->sig,10 ) || + !memcmp ("SWAPSPACE2" ,swsusp_header->sig,10 )) { +memcpy (swsusp_header->orig_sig,swsusp_header->sig,10 ); +memcpy (swsusp_header->sig,SWSUSP_SIG ,10 ); + swsusp_header->image = start; error =bio_write_page (swsusp_resume_block, - &swsusp_header,NULL ); + swsusp_header,NULL ); }else {printk (KERN_ERR "swsusp: Swap header not found!\n" ); error = -ENODEV ;
@@ -564,7 +566,7 @@ int swsusp_read(void)if (error <PAGE_SIZE )return error <0 ? error : -EFAULT ; header = (struct swsusp_info *)data_of (snapshot); - error =get_swap_reader (&handle, swsusp_header.image); + error =get_swap_reader (&handle, swsusp_header->image);if (!error) error =swap_read_page (&handle, header,NULL );if (!error)
@@ -591,17 +593,17 @@ int swsusp_check(void) resume_bdev =open_by_devnum (swsusp_resume_device,FMODE_READ );if (!IS_ERR (resume_bdev)) {set_blocksize (resume_bdev,PAGE_SIZE ); -memset (&swsusp_header,0 ,sizeof (swsusp_header)); +memset (swsusp_header,0 ,sizeof (PAGE_SIZE )); error =bio_read_page (swsusp_resume_block, - &swsusp_header,NULL ); + swsusp_header,NULL );if (error)return error; -if (!memcmp (SWSUSP_SIG , swsusp_header.sig,10 )) { -memcpy (swsusp_header.sig, swsusp_header.orig_sig,10 ); +if (!memcmp (SWSUSP_SIG , swsusp_header->sig,10 )) { +memcpy (swsusp_header->sig, swsusp_header->orig_sig,10 );/* Reset swap signature now */ error =bio_write_page (swsusp_resume_block, - &swsusp_header,NULL ); + swsusp_header,NULL ); }else {return -EINVAL ; }
@@ -632,3 +634,13 @@ void swsusp_close(void)blkdev_put (resume_bdev); } + +static int swsusp_header_init (void ) +{ + swsusp_header = (struct swsusp_header *)__get_free_page (GFP_KERNEL ); +if (!swsusp_header) +panic ("Could not allocate memory for swsusp_header\n" ); +return 0 ; +} + +core_initcall (swsusp_header_init);
_
Re: [PATCH 16/20] swsusp: do not use virt_to_page on kernel data address
Hi!
Quoted 12 lines
o
virt_to_page()call should be used on kernel linear addresses and not on kernel text and data addresses. Swsusp code uses it on kernel data (statically allocatedswsusp_header).o Allocate
swsusp_headerdynamically so thatvirt_to_page()can be used safely.o I am changing this because in next few patches,
__pa()onx86_64will no longer support kernel text and data addresses and hibernation breaks.Signed-off-by Vivek Goyal <[email protected]>
kernel/power/swap.c void swsusp_close(void) · line 646
Quoted 9 lines
kernel/power/swap.c renamed from kernel/power/swap.c~swsusp-do-not-use-virt_to_page-on-kernel-data-addr +9
-0+static int swsusp_header_init (void ) +{ + swsusp_header = (struct swsusp_header *)__get_free_page (GFP_KERNEL ); +if (!swsusp_header) +panic ("Could not allocate memory for swsusp_header\n" ); +return 0 ; +} + +core_initcall (swsusp_header_init);
I do not like the panic, but I guess it is okay as we are running during boot? (Could you add a comment?) Otherwise ok.
Pavel
Signature · 2 lines
(english) http://www.livejournal.com/~pavelmachek (cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
Re: [PATCH 16/20] swsusp: do not use virt_to_page on kernel data address
Quoted 14 lines · Pavel Machek
Hi!
Quoted 11 lines
o
virt_to_page()call should be used on kernel linear addresses and not on kernel text and data addresses. Swsusp code uses it on kernel data (statically allocatedswsusp_header).o Allocate
swsusp_headerdynamically so thatvirt_to_page()can be used safely.o I am changing this because in next few patches,
__pa()onx86_64will no longer support kernel text and data addresses and hibernation breaks.Signed-off-by Vivek Goyal <[email protected]>
Quoted 13 lines
kernel/power/swap.c void swsusp_close(void) · line 646
Quoted 9 lines
kernel/power/swap.c renamed from kernel/power/swap.c~swsusp-do-not-use-virt_to_page-on-kernel-data-addr +9
-0+static int swsusp_header_init (void ) +{ + swsusp_header = (struct swsusp_header *)__get_free_page (GFP_KERNEL ); +if (!swsusp_header) +panic ("Could not allocate memory for swsusp_header\n" ); +return 0 ; +} + +core_initcall (swsusp_header_init);I do not like the panic, but I guess it is okay as we are running during boot? (Could you add a comment?) Otherwise ok.
Hi Pavel,
Yes, it is an initcall and this memory page will be allocated during boot time. Not very sure what comment to put there. To me it seems pretty obivious with "core_initcall".
Thanks
Vivek
Re: [PATCH 16/20] swsusp: do not use virt_to_page on kernel data address
Hi!
Quoted 16 lines
Quoted 15 lines
kernel/power/swap.c void swsusp_close(void) · line 646
Quoted 11 lines
Signed-off-by Vivek Goyal <[email protected]>kernel/power/swap.c renamed from kernel/power/swap.c~swsusp-do-not-use-virt_to_page-on-kernel-data-addr +9
-0+static int swsusp_header_init (void ) +{ + swsusp_header = (struct swsusp_header *)__get_free_page (GFP_KERNEL ); +if (!swsusp_header) +panic ("Could not allocate memory for swsusp_header\n" ); +return 0 ; +} + +core_initcall (swsusp_header_init);I do not like the panic, but I guess it is okay as we are running during boot? (Could you add a comment?) Otherwise ok.
Quoted 5 lines
Hi Pavel,
Yes, it is an initcall and this memory page will be allocated during boot time. Not very sure what comment to put there. To me it seems pretty obivious with "
core_initcall".
I'd put "/* running at boot time, so allocation can't fail */" there (and maybe just replace panic with BUG_ON), but I guess that's not important.
ACK.
Pavel
Signature · 2 lines
(english) http://www.livejournal.com/~pavelmachek (cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
Re: [PATCH 16/20] swsusp: do not use virt_to_page on kernel data address
In reply to Vivek GoyalHi!
Quoted 11 lines
o
virt_to_page()call should be used on kernel linear addresses and not on kernel text and data addresses. Swsusp code uses it on kernel data (statically allocatedswsusp_header).o Allocate
swsusp_headerdynamically so thatvirt_to_page()can be used safely.o I am changing this because in next few patches,
__pa()onx86_64will no longer support kernel text and data addresses and hibernation breaks.Signed-off-by Vivek Goyal <[email protected]>
(I assume this was tested, too?)
Pavel
Signature · 2 lines
(english) http://www.livejournal.com/~pavelmachek (cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
Re: [PATCH 16/20] swsusp: do not use virt_to_page on kernel data address
Hi.
Quoted 9 lines · Pavel Machek
Hi!
Quoted 7 lines
o
virt_to_page()call should be used on kernel linear addresses and not on kernel text and data addresses. Swsusp code uses it on kernel data (statically allocatedswsusp_header).o Allocate
swsusp_headerdynamically so thatvirt_to_page()can be used safely.
Quoted 6 lines
Quoted 4 lines
o I am changing this because in next few patches,
__pa()onx86_64will no longer support kernel text and data addresses and hibernation breaks.Signed-off-by Vivek Goyal <[email protected]>(I assume this was tested, too?)
Absolutely.
Nigel
Re: [PATCH 16/20] swsusp: do not use virt_to_page on kernel data address
In reply to Pavel MachekQuoted 9 lines · Pavel Machek
Hi!
Quoted 7 lines
o
virt_to_page()call should be used on kernel linear addresses and not on kernel text and data addresses. Swsusp code uses it on kernel data (statically allocatedswsusp_header).o Allocate
swsusp_headerdynamically so thatvirt_to_page()can be used safely.
Quoted 7 lines
Quoted 4 lines
o I am changing this because in next few patches,
__pa()onx86_64will no longer support kernel text and data addresses and hibernation breaks.Signed-off-by Vivek Goyal <[email protected]>(I assume this was tested, too?)
Pavel
Yes. I have tested this and it works fine.
Thanks
Vivek
Re: [PATCH 16/20] swsusp: do not use virt_to_page on kernel data address
Hi!
Quoted 7 lines
Quoted 7 lines
Quoted 7 lines
o
virt_to_page()call should be used on kernel linear addresses and not on kernel text and data addresses. Swsusp code uses it on kernel data (statically allocatedswsusp_header).o Allocate
swsusp_headerdynamically so thatvirt_to_page()can be used safely.
Quoted 8 lines
Quoted 6 lines
Quoted 4 lines
o I am changing this because in next few patches,
__pa()onx86_64will no longer support kernel text and data addresses and hibernation breaks.Signed-off-by Vivek Goyal <[email protected]>(I assume this was tested, too?)
Yes. I have tested this and it works fine.
ACK from me, then.
Pavel
Signature · 2 lines
(english) http://www.livejournal.com/~pavelmachek (cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
PATCH 17/20 x86_64: __pa and __pa_symbol address space separation
In reply to Vivek GoyalCurrently __pa_symbol is for use with symbols in the kernel address map and __pa is for use with pointers into the physical memory map. But the code is implemented so you can usually interchange the two.
__pa which is much more common can be implemented much more cheaply if it is it doesn't have to worry about any other kernel address spaces. This is especially true with a relocatable kernel as __pa_symbol needs to peform an extra variable read to resolve the address.
There is a third macro that is added for the vsyscall data __pa_vsymbol for finding the physical addesses of vsyscall pages.
Most of this patch is simply sorting through the references to __pa or __pa_symbol and using the proper one. A little of it is continuing to use a physical address when we have it instead of recalculating it several times.
swapper_pgd is now NULL. leave_mm now uses init_mm.pgd and init_mm.pgd is initialized at boot (instead of compile time) to the physmem virtual mapping of init_level4_pgd. The physical address changed.
Except for the for EMPTY_ZERO page all of the remaining references to __pa_symbol appear to be during kernel initialization. So this should reduce the cost of __pa in the common case, even on a relocated kernel.
As this is technically a semantic change we need to be on the lookout for anything I missed. But it works for me (tm).
---
arch/i386/kernel/alternative.c | 8 ++++---- arch/i386/mm/init.c | 15 ++++++++------- arch/x86_64/kernel/machine_kexec.c | 14 +++++++------- arch/x86_64/kernel/setup.c | 9 +++++---- arch/x86_64/kernel/smp.c | 2 +- arch/x86_64/kernel/vsyscall.c | 9 +++++++-- arch/x86_64/mm/init.c | 21 +++++++++++---------- arch/x86_64/mm/pageattr.c | 16 ++++++++-------- include/asm-x86_64/page.h | 6 ++---- include/asm-x86_64/pgtable.h | 4 ++-- 10 files changed, 55 insertions(+), 49 deletions(-)
arch/i386/kernel/alternative.c renamed from arch/i386/kernel/alternative.c~x86_64-__pa-and-__pa_symbol-address-space-separation +4 -4
@@ -389,8 +389,8 @@ void __init alternative_instructions(voiif (no_replacement) {printk (KERN_INFO "(SMP-)alternatives turned off\n" );free_init_pages ("SMP alternatives" , - (unsigned long )__smp_alt_begin, - (unsigned long )__smp_alt_end); +__pa_symbol (&__smp_alt_begin), +__pa_symbol (&__smp_alt_end));return ; }
@@ -419,8 +419,8 @@ void __init alternative_instructions(voi _text, _etext); }free_init_pages ("SMP alternatives" , - (unsigned long )__smp_alt_begin, - (unsigned long )__smp_alt_end); +__pa_symbol (&__smp_alt_begin), +__pa_symbol (&__smp_alt_end)); }else {alternatives_smp_save (__smp_alt_instructions, __smp_alt_instructions_end);
arch/i386/mm/init.c renamed from arch/i386/mm/init.c~x86_64-__pa-and-__pa_symbol-address-space-separation +8 -7
@@ -774,10 +774,11 @@ void free_init_pages(char *what, unsigneunsigned long addr;for (addr = begin; addr < end; addr +=PAGE_SIZE ) { -ClearPageReserved (virt_to_page (addr)); -init_page_count (virt_to_page (addr)); -memset ((void *)addr,POISON_FREE_INITMEM ,PAGE_SIZE ); -free_page (addr); +struct page *page =pfn_to_page (addr >>PAGE_SHIFT ); +ClearPageReserved (page); +init_page_count (page); +memset (page_address (page),POISON_FREE_INITMEM ,PAGE_SIZE ); +__free_page (page); totalram_pages++; }printk (KERN_INFO "Freeing %s: %ldk freed\n" , what, (end - begin) >>10 );
@@ -786,14 +787,14 @@ void free_init_pages(char *what, unsignevoid free_initmem (void ) {free_init_pages ("unused kernel memory" , - (unsigned long )(&__init_begin), - (unsigned long )(&__init_end)); +__pa_symbol (&__init_begin), +__pa_symbol (&__init_end)); }#ifdef CONFIG_BLK_DEV_INITRD void free_initrd_mem (unsigned long start,unsigned long end) { -free_init_pages ("initrd memory" , start, end); +free_init_pages ("initrd memory" ,__pa (start),__pa (end)); }#endif
arch/x86_64/kernel/machine_kexec.c renamed from arch/x86_64/kernel/machine_kexec.c~x86_64-__pa-and-__pa_symbol-address-space-separation +7 -7
@@ -191,19 +191,19 @@ NORET_TYPE void machine_kexec(struct kim page_list[PA_CONTROL_PAGE ] =__pa (control_page); page_list[VA_CONTROL_PAGE ] = (unsigned long )relocate_kernel; - page_list[PA_PGD ] =__pa (kexec_pgd); + page_list[PA_PGD ] =__pa_symbol (&kexec_pgd); page_list[VA_PGD ] = (unsigned long )kexec_pgd; - page_list[PA_PUD_0 ] =__pa (kexec_pud0); + page_list[PA_PUD_0 ] =__pa_symbol (&kexec_pud0); page_list[VA_PUD_0 ] = (unsigned long )kexec_pud0; - page_list[PA_PMD_0 ] =__pa (kexec_pmd0); + page_list[PA_PMD_0 ] =__pa_symbol (&kexec_pmd0); page_list[VA_PMD_0 ] = (unsigned long )kexec_pmd0; - page_list[PA_PTE_0 ] =__pa (kexec_pte0); + page_list[PA_PTE_0 ] =__pa_symbol (&kexec_pte0); page_list[VA_PTE_0 ] = (unsigned long )kexec_pte0; - page_list[PA_PUD_1 ] =__pa (kexec_pud1); + page_list[PA_PUD_1 ] =__pa_symbol (&kexec_pud1); page_list[VA_PUD_1 ] = (unsigned long )kexec_pud1; - page_list[PA_PMD_1 ] =__pa (kexec_pmd1); + page_list[PA_PMD_1 ] =__pa_symbol (&kexec_pmd1); page_list[VA_PMD_1 ] = (unsigned long )kexec_pmd1; - page_list[PA_PTE_1 ] =__pa (kexec_pte1); + page_list[PA_PTE_1 ] =__pa_symbol (&kexec_pte1); page_list[VA_PTE_1 ] = (unsigned long )kexec_pte1; page_list[PA_TABLE_PAGE] =
arch/x86_64/kernel/setup.c renamed from arch/x86_64/kernel/setup.c~x86_64-__pa-and-__pa_symbol-address-space-separation +5 -4
@@ -243,11 +243,12 @@ void __init setup_arch(char **cmdline_p) init_mm.end_code = (unsigned long ) &_etext; init_mm.end_data = (unsigned long ) &_edata; init_mm.brk = (unsigned long ) &_end; + init_mm.pgd =__va (__pa_symbol (&init_level4_pgt)); - code_resource.start =virt_to_phys (&_text); - code_resource.end =virt_to_phys (&_etext)-1 ; - data_resource.start =virt_to_phys (&_etext); - data_resource.end =virt_to_phys (&_edata)-1 ; + code_resource.start =__pa_symbol (&_text); + code_resource.end =__pa_symbol (&_etext)-1 ; + data_resource.start =__pa_symbol (&_etext); + data_resource.end =__pa_symbol (&_edata)-1 ;early_identify_cpu (&boot_cpu_data);
arch/x86_64/kernel/smp.c renamed from arch/x86_64/kernel/smp.c~x86_64-__pa-and-__pa_symbol-address-space-separation +1 -1
@@ -76,7 +76,7 @@ static inline void leave_mm(int cpu)if (read_pda (mmu_state) ==TLBSTATE_OK )BUG ();cpu_clear (cpu,read_pda (active_mm)->cpu_vm_mask); -load_cr3 (swapper_pg_dir); +load_cr3 (init_mm.pgd); }/*
arch/x86_64/kernel/vsyscall.c renamed from arch/x86_64/kernel/vsyscall.c~x86_64-__pa-and-__pa_symbol-address-space-separation +7 -2
@@ -45,6 +45,11 @@#define __vsyscall (nr) __attribute__ ((unused,__section__(".vsyscall_" #nr)))#define __syscall_clobber "r11","rcx","memory" +#define __pa_vsymbol (x) \ + ({unsigned long v; \ + extern char __vsyscall_0; \ + asm("" : "=r" (v) : "0" (x)); \ + ((v - VSYSCALL_FIRST_PAGE) + __pa_symbol(&__vsyscall_0)); })struct vsyscall_gtod_data_t {seqlock_t lock;
@@ -224,10 +229,10 @@ static int vsyscall_sysctl_change(ctl_tareturn ret;/* gcc has some trouble with __va(__pa()), so just do it this way. */ - map1 =ioremap (__pa_symbol (&vsysc1),2 ); + map1 =ioremap (__pa_vsymbol (&vsysc1),2 );if (!map1)return -ENOMEM ; - map2 =ioremap (__pa_symbol (&vsysc2),2 ); + map2 =ioremap (__pa_vsymbol (&vsysc2),2 );if (!map2) { ret = -ENOMEM ; goto out;
arch/x86_64/mm/init.c renamed from arch/x86_64/mm/init.c~x86_64-__pa-and-__pa_symbol-address-space-separation +11 -10
@@ -565,11 +565,11 @@ void free_init_pages(char *what, unsigneprintk (KERN_INFO "Freeing %s: %ldk freed\n" , what, (end - begin) >>10 );for (addr = begin; addr < end; addr +=PAGE_SIZE ) { -ClearPageReserved (virt_to_page (addr)); -init_page_count (virt_to_page (addr)); -memset ((void *)(addr & ~(PAGE_SIZE -1 )), -POISON_FREE_INITMEM ,PAGE_SIZE ); -free_page (addr); +struct page *page =pfn_to_page (addr >>PAGE_SHIFT ); +ClearPageReserved (page); +init_page_count (page); +memset (page_address (page),POISON_FREE_INITMEM ,PAGE_SIZE ); +__free_page (page); totalram_pages++; } }
@@ -579,17 +579,18 @@ void free_initmem(void)memset (__initdata_begin,POISON_FREE_INITDATA , __initdata_end - __initdata_begin);free_init_pages ("unused kernel memory" , - (unsigned long )(&__init_begin), - (unsigned long )(&__init_end)); +__pa_symbol (&__init_begin), +__pa_symbol (&__init_end)); }#ifdef CONFIG_DEBUG_RODATA void mark_rodata_ro (void ) { -unsigned long addr = (unsigned long )__start_rodata; +unsigned long addr = (unsigned long )__va (__pa_symbol (&__start_rodata)); +unsigned long end = (unsigned long )__va (__pa_symbol (&__end_rodata)); -for (; addr < (unsigned long )__end_rodata; addr +=PAGE_SIZE ) +for (; addr < end; addr +=PAGE_SIZE )change_page_attr_addr (addr,1 ,PAGE_KERNEL_RO ); printk ("Write protecting the kernel read-only data: %luk\n",
@@ -608,7 +609,7 @@ void mark_rodata_ro(void)#ifdef CONFIG_BLK_DEV_INITRD void free_initrd_mem (unsigned long start,unsigned long end) { -free_init_pages ("initrd memory" , start, end); +free_init_pages ("initrd memory" ,__pa (start),__pa (end)); }#endif
arch/x86_64/mm/pageattr.c renamed from arch/x86_64/mm/pageattr.c~x86_64-__pa-and-__pa_symbol-address-space-separation +8 -8
@@ -51,7 +51,6 @@ static struct page *split_large_page(unsSetPagePrivate (base);page_private (base) =0 ; - address =__pa (address); addr = address &LARGE_PAGE_MASK ; pbase = (pte_t *)page_address (base);for (i =0 ; i <PTRS_PER_PTE ; i++, addr +=PAGE_SIZE ) {
@@ -101,13 +100,12 @@ static inline void save_page(struct page* No more special protections in this 2/4MB area - revert to a * large page again. */ -static void revert_page (unsigned long address,pgprot_t ref_prot) +static void revert_page (unsigned long address,unsigned long pfn,pgprot_t ref_prot) {pgd_t *pgd;pud_t *pud;pmd_t *pmd;pte_t large_pte; -unsigned long pfn; pgd =pgd_offset_k (address);BUG_ON (pgd_none (*pgd));
@@ -115,7 +113,6 @@ static void revert_page(unsigned long adBUG_ON (pud_none (*pud)); pmd =pmd_offset (pud, address);BUG_ON (pmd_val (*pmd) & _PAGE_PSE); - pfn = (__pa (address) &LARGE_PAGE_MASK ) >>PAGE_SHIFT ; large_pte =pfn_pte (pfn, ref_prot); large_pte =pte_mkhuge (large_pte);set_pte ((pte_t *)pmd, large_pte);
@@ -141,7 +138,8 @@ __change_page_attr(unsigned long address*/ struct page *split; ref_prot2 =pte_pgprot (pte_clrhuge (*kpte)); - split =split_large_page (address, prot, ref_prot2); + split =split_large_page (pfn <<PAGE_SHIFT , prot, + ref_prot2);if (!split)return -ENOMEM ;set_pte (kpte,mk_pte (split, ref_prot2));
@@ -160,7 +158,7 @@ __change_page_attr(unsigned long addressif (page_private (kpte_page) ==0 ) {save_page (kpte_page); -revert_page (address, ref_prot); +revert_page (address, pfn, ref_prot); }return 0 ; }
@@ -180,6 +178,7 @@ __change_page_attr(unsigned long address*/ int change_page_attr_addr (unsigned long address,int numpages,pgprot_t prot) { +unsigned long phys_base_pfn =__pa_symbol (__START_KERNEL_map) >>PAGE_SHIFT ;int err =0 ;int i;
@@ -192,10 +191,11 @@ int change_page_attr_addr(unsigned longbreak ;/* Handle kernel mapping too which aliases part of the * lowmem */ -if (__pa (address) <KERNEL_TEXT_SIZE ) { +if ((pfn >= phys_base_pfn) && + ((pfn - phys_base_pfn) < (KERNEL_TEXT_SIZE >>PAGE_SHIFT ))) {unsigned long addr2;pgprot_t prot2; - addr2 = __START_KERNEL_map +__pa (address); + addr2 = __START_KERNEL_map + ((pfn - phys_base_pfn) <<PAGE_SHIFT );/* Make sure the kernel mappings stay executable */ prot2 =pte_pgprot (pte_mkexec (pfn_pte (0 , prot))); err = __change_page_attr(addr2, pfn, prot2,
include/asm-x86_64/page.h renamed from include/asm-x86_64/page.h~x86_64-__pa-and-__pa_symbol-address-space-separation +2 -4
@@ -102,17 +102,15 @@ typedef struct { unsigned long pgprot; }/* Note: __pa(&symbol_visible_to_c) should be always replaced with __pa_symbol. Otherwise you risk miscompilation. */ -#define __pa (x) (((unsigned long)(x)>=__START_KERNEL_map)?(unsigned long)(x) - (unsigned long)__START_KERNEL_map:(unsigned long)(x) - PAGE_OFFSET) +#define __pa (x) ((unsigned long)(x) - PAGE_OFFSET)/* __pa_symbol should be used for C visible symbols. This seems to be the official gcc blessed way to do such arithmetic. */ #define __pa_symbol (x) \ ({unsigned long v; \ asm("" : "=r" (v) : "0" (x)); \ - __pa(v); }) + (v - __START_KERNEL_map); })#define __va (x) ((void *)((unsigned long)(x)+PAGE_OFFSET)) -#define __boot_va (x) __va(x) -#define __boot_pa (x) __pa(x)#ifdef CONFIG_FLATMEM #define pfn_valid (pfn) ((pfn) < end_pfn)#endif
include/asm-x86_64/pgtable.h renamed from include/asm-x86_64/pgtable.h~x86_64-__pa-and-__pa_symbol-address-space-separation +2 -2
@@ -20,7 +20,7 @@ extern pmd_t level2_kernel_pgt[512];extern pgd_t init_level4_pgt[];extern unsigned long __supported_pte_mask; -#define swapper_pg_dir init_level4_pgt +#define swapper_pg_dir ((pgd_t *)NULL)extern void paging_init (void );extern void clear_kernel_mapping (unsigned long addr,unsigned long size);
@@ -30,7 +30,7 @@ extern void clear_kernel_mapping(unsigne* for zero-mapped memory areas etc.. */ extern unsigned long empty_zero_page[PAGE_SIZE /sizeof (unsigned long )]; -#define ZERO_PAGE (vaddr) (virt_to_page(empty_zero_page)) +#define ZERO_PAGE (vaddr) (pfn_to_page(__pa_symbol(&empty_zero_page) >> PAGE_SHIFT))#endif /* !__ASSEMBLY__ */
_
PATCH 18/20 x86_64: Relocatable Kernel Support
In reply to Vivek GoyalThis patch modifies the x86_64 kernel so that it can be loaded and run at any 2M aligned address, below 512G. The technique used is to compile the decompressor with -fPIC and modify it so the decompressor is fully relocatable. For the main kernel the page tables are modified so the kernel remains at the same virtual address. In addition a variable phys_base is kept that holds the physical address the kernel is loaded at. __pa_symbol is modified to add that when we take the address of a kernel symbol.
When loaded with a normal bootloader the decompressor will decompress the kernel to 2M and it will run there. This both ensures the relocation code is always working, and makes it easier to use 2M pages for the kernel and the cpu.
---
arch/x86_64/Kconfig | 50 ++++ arch/x86_64/boot/compressed/Makefile | 12 - arch/x86_64/boot/compressed/head.S | 322 +++++++++++++++++++++++--------- arch/x86_64/boot/compressed/misc.c | 251 +++++++++++++----------- arch/x86_64/boot/compressed/vmlinux.lds | 44 ++++ arch/x86_64/boot/compressed/vmlinux.scr | 9 arch/x86_64/kernel/head.S | 225 ++++++++++++---------- arch/x86_64/kernel/suspend_asm.S | 7 include/asm-x86_64/page.h | 6 9 files changed, 596 insertions(+), 330 deletions(-)
arch/x86_64/boot/compressed/head.S renamed from arch/x86_64/boot/compressed/head.S~x86_64-Relocatable-kernel-support +234 -88
@@ -26,116 +26,262 @@ #include <linux/linkage.h> #include <asm/segment.h> +#include <asm/pgtable.h> #include <asm/page.h> +#include <asm/msr.h> +.section ".text.head" .code32 .globl startup_32 - + startup_32: cld cli - movl $(__KERNEL_DS),%eax - movl %eax,%ds - movl %eax,%es - movl %eax,%fs - movl %eax,%gs - - lss stack_start,%esp - xorl %eax,%eax -1: incl %eax # check that A20 really IS enabled - movl %eax,0x000000 # loop forever if it isn't - cmpl %eax,0x100000 - je 1b + movl $(__KERNEL_DS), %eax + movl %eax, %ds + movl %eax, %es + movl %eax, %ss + +/* Calculate the delta between where we were compiled to run + * at and where we were actually loaded at. This can only be done + * with a short local call on x86. Nothing else will tell us what + * address we are running at. The reserved chunk of the real-mode + * data at 0x34-0x3f are used as the stack for this calculation. + * Only 4 bytes are needed. + */ + leal 0x40(%esi), %esp + call 1f +1: popl %ebp + subl $1b, %ebp + +/* Compute the delta between where we were compiled to run at + * and where the code will actually run at. + */ +/* %ebp contains the address we are loaded at by the boot loader and %ebx + * contains the address where we should move the kernel image temporarily + * for safe in-place decompression. + */ + +#ifdef CONFIG_RELOCATABLE + movl %ebp, %ebx + addl $(LARGE_PAGE_SIZE -1), %ebx + andl $LARGE_PAGE_MASK, %ebx +#else + movl $CONFIG_PHYSICAL_START, %ebx +#endif + + /* Replace the compressed data size with the uncompressed size */ + subl input_len(%ebp), %ebx + movl output_len(%ebp), %eax + addl %eax, %ebx + /* Add 8 bytes for every 32K input block */ + shrl $12, %eax + addl %eax, %ebx + /* Add 32K + 18 bytes of extra slack and align on a 4K boundary */ + addl $(32768 + 18 + 4095), %ebx + andl $~4095, %ebx /* - * Initialize eflags. Some BIOS's leave bits like NT set. This would - * confuse the debugger if this code is traced. - * XXX - best to initialize before switching to protected mode. + * Prepare for entering 64 bit mode */ - pushl $0 - popfl + + /* Load new GDT with the 64bit segments using 32bit descriptor */ + leal gdt(%ebp), %eax + movl %eax, gdt+2(%ebp) + lgdt gdt(%ebp) + + /* Enable PAE mode */ + xorl %eax, %eax + orl $(1 << 5), %eax + movl %eax, %cr4 + + /* + * Build early 4G boot pagetable + */ + /* Initialize Page tables to 0*/ + leal pgtable(%ebx), %edi + xorl %eax, %eax + movl $((4096*6)/4), %ecx + rep stosl + + /* Build Level 4 */ + leal pgtable + 0(%ebx), %edi + leal 0x1007 (%edi), %eax + movl %eax, 0(%edi) + + /* Build Level 3 */ + leal pgtable + 0x1000(%ebx), %edi + leal 0x1007(%edi), %eax + movl $4, %ecx +1: movl %eax, 0x00(%edi) + addl $0x00001000, %eax + addl $8, %edi + decl %ecx + jnz 1b + + /* Build Level 2 */ + leal pgtable + 0x2000(%ebx), %edi + movl $0x00000183, %eax + movl $2048, %ecx +1: movl %eax, 0(%edi) + addl $0x00200000, %eax + addl $8, %edi + decl %ecx + jnz 1b + + /* Enable the boot page tables */ + leal pgtable(%ebx), %eax + movl %eax, %cr3 + + /* Enable Long mode in EFER (Extended Feature Enable Register) */ + movl $MSR_EFER, %ecx + rdmsr + btsl $_EFER_LME, %eax + wrmsr + + /* Setup for the jump to 64bit mode + * + * When the jump is performend we will be in long mode but + * in 32bit compatibility mode with EFER.LME = 1, CS.L = 0, CS.D = 1 + * (and in turn EFER.LMA = 1). To jump into 64bit mode we use + * the new gdt/idt that has __KERNEL_CS with CS.L = 1. + * We place all of the values on our mini stack so lret can + * used to perform that far jump. + */ + pushl $__KERNEL_CS + leal startup_64(%ebp), %eax + pushl %eax + + /* Enter paged protected Mode, activating Long Mode */ + movl $0x80000001, %eax /* Enable Paging and Protected mode */ + movl %eax, %cr0 + + /* Jump from 32bit compatibility mode into 64bit mode. */ + lret + + /* Be careful here startup_64 needs to be at a predictable + * address so I can export it in an ELF header. Bootloaders + * should look at the ELF header to find this address, as + * it may change in the future. + */ + .code64 + .org 0x100 +ENTRY(startup_64) + /* We come here either from startup_32 or directly from a + * 64bit bootloader. If we come here from a bootloader we depend on + * an identity mapped page table being provied that maps our + * entire text+data+bss and hopefully all of memory. + */ + + /* Setup data segments. */ + xorl %eax, %eax + movl %eax, %ds + movl %eax, %es + movl %eax, %ss + + /* Compute the decompressed kernel start address. It is where + * we were loaded at aligned to a 2M boundary. %rbp contains the + * decompressed kernel start address. + * + * If it is a relocatable kernel then decompress and run the kernel + * from load address aligned to 2MB addr, otherwise decompress and + * run the kernel from CONFIG_PHYSICAL_START + */ + + /* Start with the delta to where the kernel will run at. */ +#ifdef CONFIG_RELOCATABLE + leaq startup_32(%rip) /* - $startup_32 */, %rbp + addq $(LARGE_PAGE_SIZE - 1), %rbp + andq $LARGE_PAGE_MASK, %rbp + movq %rbp, %rbx +#else + movq $CONFIG_PHYSICAL_START, %rbp + movq %rbp, %rbx +#endif + + /* Replace the compressed data size with the uncompressed size */ + movl input_len(%rip), %eax + subq %rax, %rbx + movl output_len(%rip), %eax + addq %rax, %rbx + /* Add 8 bytes for every 32K input block */ + shrq $12, %rax + addq %rax, %rbx + /* Add 32K + 18 bytes of extra slack and align on a 4K boundary */ + addq $(32768 + 18 + 4095), %rbx + andq $~4095, %rbx + +/* Copy the compressed kernel to the end of our buffer + * where decompression in place becomes safe. + */ + leaq _end(%rip), %r8 + leaq _end(%rbx), %r9 + movq $_end /* - $startup_32 */, %rcx +1: subq $8, %r8 + subq $8, %r9 + movq 0(%r8), %rax + movq %rax, 0(%r9) + subq $8, %rcx + jnz 1b + +/* + * Jump to the relocated address. + */ + leaq relocated(%rbx), %rax + jmp *%rax + +.section ".text" +relocated: + /* * Clear BSS */ - xorl %eax,%eax - movl $_edata,%edi - movl $_end,%ecx - subl %edi,%ecx + xorq %rax, %rax + leaq _edata(%rbx), %rdi + leaq _end(%rbx), %rcx + subq %rdi, %rcx cld rep stosb + + /* Setup the stack */ + leaq user_stack_end(%rip), %rsp + + /* zero EFLAGS after setting rsp */ + pushq $0 + popfq + /* * Do the decompression, and jump to the new kernel.. */ - subl $16,%esp # place for structure on the stack - movl %esp,%eax - pushl %esi # real mode pointer as second arg - pushl %eax # address of structure as first arg - call decompress_kernel - orl %eax,%eax - jnz 3f - addl $8,%esp - xorl %ebx,%ebx - ljmp $(__KERNEL_CS), $__PHYSICAL_START - -/* - * We come here, if we were loaded high. - * We need to move the move-in-place routine down to 0x1000 - * and then start it with the buffer addresses in registers, - * which we got from the stack. - */ -3: - movl %esi,%ebx - movl $move_routine_start,%esi - movl $0x1000,%edi - movl $move_routine_end,%ecx - subl %esi,%ecx - addl $3,%ecx - shrl $2,%ecx - cld - rep - movsl + pushq %rsi # Save the real mode argument + movq %rsi, %rdi # real mode address + leaq _heap(%rip), %rsi # _heap + leaq input_data(%rip), %rdx # input_data + movl input_len(%rip), %eax + movq %rax, %rcx # input_len + movq %rbp, %r8 # output + call decompress_kernel + popq %rsi - popl %esi # discard the address - addl $4,%esp # real mode pointer - popl %esi # low_buffer_start - popl %ecx # lcount - popl %edx # high_buffer_start - popl %eax # hcount - movl $__PHYSICAL_START,%edi - cli # make sure we don't get interrupted - ljmp $(__KERNEL_CS), $0x1000 # and jump to the move routine /* - * Routine (template) for moving the decompressed kernel in place, - * if we were high loaded. This _must_ PIC-code ! + * Jump to the decompressed kernel. */ -move_routine_start: - movl %ecx,%ebp - shrl $2,%ecx - rep - movsl - movl %ebp,%ecx - andl $3,%ecx - rep - movsb - movl %edx,%esi - movl %eax,%ecx # NOTE: rep movsb won't move if %ecx == 0 - addl $3,%ecx - shrl $2,%ecx - rep - movsl - movl %ebx,%esi # Restore setup pointer - xorl %ebx,%ebx - ljmp $(__KERNEL_CS), $__PHYSICAL_START -move_routine_end: + jmp *%rbp - -/* Stack for uncompression */ - .align 32 -user_stack: + .data +gdt: + .word gdt_end - gdt + .long gdt + .word 0 + .quad 0x0000000000000000 /* NULL descriptor */ + .quad 0x00af9a000000ffff /* __KERNEL_CS */ + .quad 0x00cf92000000ffff /* __KERNEL_DS */ +gdt_end: + .bss +/* Stack for uncompression */ + .balign 4 +user_stack: .fill 4096,4,0 -stack_start: - .long user_stack+4096 - .word __KERNEL_DS - +user_stack_end:
arch/x86_64/boot/compressed/Makefile renamed from arch/x86_64/boot/compressed/Makefile~x86_64-Relocatable-kernel-support +5 -7
@@ -8,16 +8,14 @@ targets := vmlinux vmlinux.bin vmlinux.bin.gz head.o misc.o piggy.o EXTRA_AFLAGS := -traditional -AFLAGS := $(subst -m64,-m32,$(AFLAGS)) # cannot use EXTRA_CFLAGS because base CFLAGS contains -mkernel which conflicts with # -m32 -CFLAGS := -m32 -D__KERNEL__ -Iinclude -O2 -fno-strict-aliasing -LDFLAGS := -m elf_i386 +CFLAGS := -m64 -D__KERNEL__ -Iinclude -O2 -fno-strict-aliasing -fPIC -mcmodel=small -fno-builtin +LDFLAGS := -m elf_x86_64 -LDFLAGS_vmlinux := -Ttext $(IMAGE_OFFSET) -e startup_32 -m elf_i386 - -$(obj)/vmlinux: $(obj)/head.o $(obj)/misc.o $(obj)/piggy.o FORCE +LDFLAGS_vmlinux := -T +$(obj)/vmlinux: $(src)/vmlinux.lds $(obj)/head.o $(obj)/misc.o $(obj)/piggy.o FORCE $(call if_changed,ld) @:
@@ -27,7 +25,7 @@ $(obj)/vmlinux.bin: vmlinux FORCE $(obj)/vmlinux.bin.gz: $(obj)/vmlinux.bin FORCE $(call if_changed,gzip) -LDFLAGS_piggy.o := -r --format binary --oformat elf32-i386 -T +LDFLAGS_piggy.o := -r --format binary --oformat elf64-x86-64 -T $(obj)/piggy.o: $(obj)/vmlinux.scr $(obj)/vmlinux.bin.gz FORCE $(call if_changed,ld)
arch/x86_64/boot/compressed/misc.c renamed from arch/x86_64/boot/compressed/misc.c~x86_64-Relocatable-kernel-support +132 -119
310 lines not on this page · raw message
arch/x86_64/boot/compressed/vmlinux.lds new file +44 -0
44 lines not on this page · raw message
arch/x86_64/boot/compressed/vmlinux.scr renamed from arch/x86_64/boot/compressed/vmlinux.scr~x86_64-Relocatable-kernel-support +5 -4
@@ -1,9 +1,10 @@ SECTIONS { - .data : { + .text.compressed : { input_len = .; - LONG(input_data_end - input_data) input_data = .; - *(.data) - input_data_end = .; + LONG(input_data_end - input_data) input_data = .; + *(.data) + output_len = . - 4; + input_data_end = .; } }
arch/x86_64/Kconfig renamed from arch/x86_64/Kconfig~x86_64-Relocatable-kernel-support +42 -8
65 lines not on this page · raw message
arch/x86_64/kernel/head.S renamed from arch/x86_64/kernel/head.S~x86_64-Relocatable-kernel-support +126 -99
307 lines not on this page · raw message
arch/x86_64/kernel/suspend_asm.S renamed from arch/x86_64/kernel/suspend_asm.S~x86_64-Relocatable-kernel-support +4 -3
@@ -71,9 +71,10 @@ loop: jmp loop done: /* go back to the original page tables */ - leaq init_level4_pgt(%rip), %rax - subq $__START_KERNEL_map, %rax - movq %rax, %cr3 + movq $(init_level4_pgt - __START_KERNEL_map), %rax + addq phys_base(%rip), %rax + movq %rax, %cr3 + /* Flush TLB, including "global" things (vmalloc) */ movq mmu_cr4_features(%rip), %rax movq %rax, %rdx
include/asm-x86_64/page.h renamed from include/asm-x86_64/page.h~x86_64-Relocatable-kernel-support +4 -2
@@ -61,6 +61,8 @@ typedef struct { unsigned long pgd; } pgtypedef struct {unsigned long pgprot; }pgprot_t ; +extern unsigned long phys_base; +#define pte_val (x) ((x).pte)#define pmd_val (x) ((x).pmd)#define pud_val (x) ((x).pud)
@@ -101,14 +103,14 @@ typedef struct { unsigned long pgprot; }#define PAGE_OFFSET __PAGE_OFFSET/* Note: __pa(&symbol_visible_to_c) should be always replaced with __pa_symbol. -Otherwise you risk miscompilation. */ +Otherwise you risk miscompilation. */ #define __pa (x) ((unsigned long)(x) - PAGE_OFFSET)/* __pa_symbol should be used for C visible symbols. This seems to be the official gcc blessed way to do such arithmetic. */ #define __pa_symbol (x) \ ({unsigned long v; \ asm("" : "=r" (v) : "0" (x)); \ - (v - __START_KERNEL_map); }) + ((v - __START_KERNEL_map) + phys_base); })#define __va (x) ((void *)((unsigned long)(x)+PAGE_OFFSET))#ifdef CONFIG_FLATMEM
_
PATCH 19/20 x86_64: Extend bzImage protocol for relocatable bzImage
In reply to Vivek Goyalo Extend the bzImage protocol (same as i386) to allow bzImage loaders to load the protected mode kernel at non-1MB address. Now protected mode component is relocatable and can be loaded at non-1MB addresses.
o As of today kdump uses it to run a second kernel from a reserved memory area.
---
arch/x86_64/boot/setup.S | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-)
arch/x86_64/boot/setup.S renamed from arch/x86_64/boot/setup.S~x86_64-extend-bzImage-protocol-for-relocatable-bzImage +11 -2
@@ -80,7 +80,7 @@ start: # This is the setup header, and it must start at %cs:2 (old 0x9020:2) .ascii "HdrS" # header signature - .word 0x0204 # header version number (>= 0x0105) + .word 0x0205 # header version number (>= 0x0105) # or else old loadlin-1.5 will fail) realmode_swtch: .word 0, 0 # default_switch, SETUPSEG start_sys_seg: .word SYSSEG
@@ -155,7 +155,16 @@ cmd_line_ptr: .long 0 # (Header versio # low memory 0x10000 or higher. ramdisk_max: .long 0xffffffff - +kernel_alignment: .long 0x200000 # physical addr alignment required for + # protected mode relocatable kernel +#ifdef CONFIG_RELOCATABLE +relocatable_kernel: .byte 1 +#else +relocatable_kernel: .byte 0 +#endif +pad2: .byte 0 +pad3: .word 0 + trampoline: call start_of_setup .align 16 # The offset at this point is 0x240
_
PATCH 20/20 x86_64: Move cpu verification code to common file
In reply to Vivek Goyalo This patch moves the code to verify long mode and SSE to a common file. This code is now shared by trampoline.S, wakeup.S, boot/setup.S and boot/compressed/head.S
o So far we used to do very limited check in trampoline.S, wakeup.S and in 32bit entry point. Now all the entry paths are forced to do the exhaustive check, including SSE because verify_cpu is shared.
o I am keeping this patch as last in the x86 relocatable series because previous patches have got quite some amount of testing done and don't want to distrub that. So that if there is problem introduced by this patch, at least it can be easily isolated.
---
arch/x86_64/boot/compressed/head.S | 19 ++++++ arch/x86_64/boot/setup.S | 65 ++------------------- arch/x86_64/kernel/acpi/wakeup.S | 30 +++++----- arch/x86_64/kernel/trampoline.S | 51 +---------------- arch/x86_64/kernel/verify_cpu.S | 110 +++++++++++++++++++++++++++++++++++++ 5 files changed, 152 insertions(+), 123 deletions(-)
arch/x86_64/boot/compressed/head.S renamed from arch/x86_64/boot/compressed/head.S~x86_64-move-cpu-verfication-code-to-common-file +18 -1
@@ -54,6 +54,15 @@ startup_32: 1: popl %ebp subl $1b, %ebp +/* setup a stack and make sure cpu supports long mode. */ + movl $user_stack_end, %eax + addl %ebp, %eax + movl %eax, %esp + + call verify_cpu + testl %eax, %eax + jnz no_longmode + /* Compute the delta between where we were compiled to run at * and where the code will actually run at. */
@@ -159,13 +168,21 @@ startup_32: /* Jump from 32bit compatibility mode into 64bit mode. */ lret +no_longmode: + /* This isn't an x86-64 CPU so hang */ +1: + hlt + jmp 1b + +#include "../../kernel/verify_cpu.S" + /* Be careful here startup_64 needs to be at a predictable * address so I can export it in an ELF header. Bootloaders * should look at the ELF header to find this address, as * it may change in the future. */ .code64 - .org 0x100 + .org 0x200 ENTRY(startup_64) /* We come here either from startup_32 or directly from a * 64bit bootloader. If we come here from a bootloader we depend on
arch/x86_64/boot/setup.S renamed from arch/x86_64/boot/setup.S~x86_64-move-cpu-verfication-code-to-common-file +6 -59
77 lines not on this page · raw message
arch/x86_64/kernel/acpi/wakeup.S renamed from arch/x86_64/kernel/acpi/wakeup.S~x86_64-move-cpu-verfication-code-to-common-file +15 -15
@@ -43,6 +43,11 @@ wakeup_code: cmpl $0x12345678, %eax jne bogus_real_magic + call verify_cpu # Verify the cpu supports long + # mode + testl %eax, %eax + jnz no_longmode + testl $1, video_flags - wakeup_code jz 1f lcall $0xc000,$3
@@ -92,18 +97,6 @@ wakeup_32: # Running in this code, but at low address; paging is not yet turned on. movb $0xa5, %al ; outb %al, $0x80 - /* Check if extended functions are implemented */ - movl $0x80000000, %eax - cpuid - cmpl $0x80000000, %eax - jbe bogus_cpu - wbinvd - mov $0x80000001, %eax - cpuid - btl $29, %edx - jnc bogus_cpu - movl %edx,%edi - movl $__KERNEL_DS, %eax movl %eax, %ds
@@ -123,6 +116,11 @@ wakeup_32: leal (wakeup_level4_pgt - wakeup_code)(%esi), %eax movl %eax, %cr3 + /* Check if nx is implemented */ + movl $0x80000001, %eax + cpuid + movl %edx,%edi + /* Enable Long Mode */ xorl %eax, %eax btsl $_EFER_LME, %eax
@@ -244,10 +242,12 @@ bogus_64_magic: movb $0xb3,%al ; outb %al,$0x80 jmp bogus_64_magic -bogus_cpu: - movb $0xbc,%al ; outb %al,$0x80 - jmp bogus_cpu +.code16 +no_longmode: + movb $0xbc,%al ; outb %al,$0x80 + jmp no_longmode +#include "../verify_cpu.S" /* This code uses an extended set of video mode numbers. These include: * Aliases for standard modes
arch/x86_64/kernel/trampoline.S renamed from arch/x86_64/kernel/trampoline.S~x86_64-move-cpu-verfication-code-to-common-file +3 -48
66 lines not on this page · raw message
arch/x86_64/kernel/verify_cpu.S new file +110 -0
110 lines not on this page · raw message
_
Quoted 5 lines · Vivek Goyal
Hi,
Here is another attempt on
x86_64relocatable bzImage patches(V4). This patchset makes a bzImage relocatable and same kernel binary can be loaded and run from different physical addresses.
have these patches been extensively tested with various suspend scenarios? (S1,S3,S4 in acpi speak or s2ram and s2disk in Linux speak)
Quoted 10 lines · Arjan van de Ven
Quoted 5 lines · Vivek Goyal
Hi,
Here is another attempt on
x86_64relocatable bzImage patches(V4). This patchset makes a bzImage relocatable and same kernel binary can be loaded and run from different physical addresses.have these patches been extensively tested with various suspend scenarios? (S1,S3,S4 in acpi speak or s2ram and s2disk in Linux speak)
It should be noted what broke was the non-portable constructs in the generic suspend code.
In particular using __pa() outside of architecture code is not allowed. Using virt_to_phys() on addresses not part of the kernel's linear mapping is not generically supported.
text/data are not required to be part of the kernel's linear mapping.
This patchset now causes all code using these non-portable constructs to fail on x86_64. Which I think is a good thing so we can more easily spot these kinds of problems.
Patches 15 and 16 appear to make the swpsuspend code rely on portable
constructs. I will let Vivek reply to the amount of testing he has
done in this area.
Eric
Hi.
Quoted 10 lines · Arjan van de Ven
Quoted 5 lines · Vivek Goyal
Hi,
Here is another attempt on
x86_64relocatable bzImage patches(V4). This patchset makes a bzImage relocatable and same kernel binary can be loaded and run from different physical addresses.have these patches been extensively tested with various suspend scenarios? (S1,S3,S4 in acpi speak or s2ram and s2disk in Linux speak)
We did work on this for RHEL5, getting relocatable kernel support working fine with S4. While doing it and since, I've been running Suspend2 with the same patch.
Since that work, Vivek has done more modifications, but I can confirm that the basic design is reliable with S4. Haven't tried S3, but can do. Will report back shortly.
Regards,
Nigel
Hi.
Quoted 14 lines · Nigel Cunningham
Hi.
Quoted 10 lines · Arjan van de Ven
Quoted 5 lines · Vivek Goyal
Hi,
Here is another attempt on
x86_64relocatable bzImage patches(V4). This patchset makes a bzImage relocatable and same kernel binary can be loaded and run from different physical addresses.have these patches been extensively tested with various suspend scenarios? (S1,S3,S4 in acpi speak or s2ram and s2disk in Linux speak)
Quoted 7 lines
We did work on this for RHEL5, getting relocatable kernel support working fine with S4. While doing it and since, I've been running Suspend2 with the same patch.
Since that work, Vivek has done more modifications, but I can confirm that the basic design is reliable with S4. Haven't tried S3, but can do. Will report back shortly.
S3 works okay here with a relocatable x86_64 kernel (2.6.20).
Regards,
Nigel
Quoted 21 lines · Nigel Cunningham
Hi.
Quoted 18 lines · Nigel Cunningham
Hi.
Quoted 10 lines · Arjan van de Ven
Quoted 5 lines · Vivek Goyal
Hi,
Here is another attempt on
x86_64relocatable bzImage patches(V4). This patchset makes a bzImage relocatable and same kernel binary can be loaded and run from different physical addresses.have these patches been extensively tested with various suspend scenarios? (S1,S3,S4 in acpi speak or s2ram and s2disk in Linux speak)
We did work on this for RHEL5, getting relocatable kernel support working fine with S4. While doing it and since, I've been running Suspend2 with the same patch.
Quoted 6 lines
Quoted 3 lines
Since that work, Vivek has done more modifications, but I can confirm that the basic design is reliable with S4. Haven't tried S3, but can do. Will report back shortly.
S3 works okay here with a relocatable
x86_64kernel (2.6.20).
Hi Nigel,
Is it possible to test S3 with 2.6.21-rc2 kernels also. Right now I don't have access to any machine supporting S3. I tested it at the time of my last posting and it had worked well. Appreciate your help.
Thanks
Vivek
Nigel Cunningham
Acked-byHi.
Quoted 26 lines · Vivek Goyal
Quoted 25 lines · Nigel Cunningham
Hi.
Quoted 21 lines · Nigel Cunningham
Hi.
Quoted 10 lines · Arjan van de Ven
Quoted 5 lines · Vivek Goyal
Hi,
Here is another attempt on
x86_64relocatable bzImage patches(V4). This patchset makes a bzImage relocatable and same kernel binary can be loaded and run from different physical addresses.have these patches been extensively tested with various suspend scenarios? (S1,S3,S4 in acpi speak or s2ram and s2disk in Linux speak)
We did work on this for RHEL5, getting relocatable kernel support working fine with S4. While doing it and since, I've been running Suspend2 with the same patch.
Since that work, Vivek has done more modifications, but I can confirm that the basic design is reliable with S4. Haven't tried S3, but can do. Will report back shortly.
Quoted 8 lines
Quoted 2 lines
S3 works okay here with a relocatable
x86_64kernel (2.6.20).Hi Nigel,
Is it possible to test S3 with 2.6.21-rc2 kernels also. Right now I don't have access to any machine supporting S3. I tested it at the time of my last posting and it had worked well. Appreciate your help.
Tested with rc3 (rc2 wouldn't compile), and it works fine.
If you're willing, please add
or
to the hibernation related parts as you see appropriate, since I helped (albeit in a minor way compared to your work and Eric's work) with preparing and testing them for RHEL5 and have confirmed they're still ok in this version.
Regards,
Nigel
Quoted 32 lines · Nigel Cunningham
Hi.
Quoted 29 lines · Vivek Goyal
Quoted 27 lines · Nigel Cunningham
Hi.
Quoted 14 lines · Nigel Cunningham
Hi.
Quoted 10 lines · Arjan van de Ven
Quoted 5 lines · Vivek Goyal
Hi,
Here is another attempt on
x86_64relocatable bzImage patches(V4). This patchset makes a bzImage relocatable and same kernel binary can be loaded and run from different physical addresses.have these patches been extensively tested with various suspend scenarios? (S1,S3,S4 in acpi speak or s2ram and s2disk in Linux speak)
Quoted 7 lines
We did work on this for RHEL5, getting relocatable kernel support working fine with S4. While doing it and since, I've been running Suspend2 with the same patch.
Since that work, Vivek has done more modifications, but I can confirm that the basic design is reliable with S4. Haven't tried S3, but can do. Will report back shortly.
S3 works okay here with a relocatable
x86_64kernel (2.6.20).
Quoted 8 lines
Quoted 5 lines
Hi Nigel,
Is it possible to test S3 with 2.6.21-rc2 kernels also. Right now I don't have access to any machine supporting S3. I tested it at the time of my last posting and it had worked well. Appreciate your help.
Tested with rc3 (rc2 wouldn't compile), and it works fine.
Thanks a lot Nigel.
Quoted 4 lines
If you're willing, please add
Signed-off-by Nigel Cunningham <[email protected]>
Quoted 8 lines
or
Acked-by Nigel Cunningham <[email protected]>to the hibernation related parts as you see appropriate, since I helped (albeit in a minor way compared to your work and Eric's work) with preparing and testing them for RHEL5 and have confirmed they're still ok in this version.
Sure. You have helped a lot. I think either Andi or Andrew needs to add "Acked-by:" string while adding the hibernation related patches (Assuming they decide do pick up the patches.)
Thanks
Vivek
Quoted 21 lines · Nigel Cunningham
Hi.
Quoted 18 lines · Nigel Cunningham
Hi.
Quoted 10 lines · Arjan van de Ven
Quoted 5 lines · Vivek Goyal
Hi,
Here is another attempt on
x86_64relocatable bzImage patches(V4). This patchset makes a bzImage relocatable and same kernel binary can be loaded and run from different physical addresses.have these patches been extensively tested with various suspend scenarios? (S1,S3,S4 in acpi speak or s2ram and s2disk in Linux speak)
We did work on this for RHEL5, getting relocatable kernel support working fine with S4. While doing it and since, I've been running Suspend2 with the same patch.
Quoted 6 lines
Quoted 3 lines
Since that work, Vivek has done more modifications, but I can confirm that the basic design is reliable with S4. Haven't tried S3, but can do. Will report back shortly.
S3 works okay here with a relocatable
x86_64kernel (2.6.20).
Ok. Got hold of a system which supports Standby mode (S1) and it works fine with 2.6.21-rc2 + relocatable patchset.
Thanks
Vivek
Quoted 10 lines · Arjan van de Ven
Quoted 5 lines · Vivek Goyal
Hi,
Here is another attempt on
x86_64relocatable bzImage patches(V4). This patchset makes a bzImage relocatable and same kernel binary can be loaded and run from different physical addresses.have these patches been extensively tested with various suspend scenarios? (S1,S3,S4 in acpi speak or s2ram and s2disk in Linux speak)
Hi Arjan,
I have tested these patches for suspend to RAM and suspend to disk and they work fine. In the past we had few issues with suspend to disk and now these issues have been resolved in this patchset.
Thanks
Vivek
Andi Kleen
AppliedQuoted 5 lines · Vivek Goyal
Hi,
Here is another attempt on
x86_64relocatable bzImage patches(V4). This patchset makes a bzImage relocatable and same kernel binary can be loaded and run from different physical addresses.
I merged them all for now. Thanks.
-Andi