Re: amd64-agp vs. swsusp

Michal Schmidt
2005-07-21T10:43:55Z

[-- Attachment #1: Type: text/plain, Size: 589 bytes --]

Pavel Machek wrote:
> Long time ago there were i386 problems because we assumed that kernel
> is mapped in one big mapping and agp broke that assumption. Copying
> pages backwards "fixed" it (and then we done proper fix). It should
> not be, but it seems similar to this problem....

Do you mean this patch of yours?:
http://www.ussg.iu.edu/hypermail/linux/kernel/0404.3/0640.html

I'm trying to do something similar for x86_64. See the attached patch.
Unfortunately, it doesn't help. The behaviour seems unchanged (resume
still works iff amd64-agp wasn't loaded before suspend).

Michal

[-- Attachment #2: swsusp-amd64-pgdir.diff --]
[-- Type: text/x-patch, Size: 1497 bytes --]

diff -Nurp -X dontdiff.new linux-mm/arch/x86_64/kernel/suspend_asm.S linux-mm.mich/arch/x86_64/kernel/suspend_asm.S
--- linux-mm/arch/x86_64/kernel/suspend_asm.S 2005-06-30 01:00:53.000000000 +0200
+++ linux-mm.mich/arch/x86_64/kernel/suspend_asm.S 2005-07-21 11:53:17.000000000 +0200
@@ -41,7 +41,7 @@ ENTRY(swsusp_arch_suspend)

ENTRY(swsusp_arch_resume)
/* set up cr3 */
- leaq init_level4_pgt(%rip),%rax
+ leaq swsusp_level4_pgt(%rip),%rax
subq $__START_KERNEL_map,%rax
movq %rax,%cr3

diff -Nurp -X dontdiff.new linux-mm/arch/x86_64/mm/init.c linux-mm.mich/arch/x86_64/mm/init.c
--- linux-mm/arch/x86_64/mm/init.c 2005-07-18 19:48:12.000000000 +0200
+++ linux-mm.mich/arch/x86_64/mm/init.c 2005-07-21 11:21:36.000000000 +0200
@@ -310,10 +310,32 @@ void __init init_memory_mapping(unsigned

extern struct x8664_pda cpu_pda[NR_CPUS];

+#ifdef CONFIG_SOFTWARE_SUSPEND
+/*
+ * Swap suspend & friends need this for resume because things like the intel-agp
+ * driver might have split up a kernel 4MB mapping.
+ */
+char __nosavedata swsusp_level4_pgt[PAGE_SIZE]
+ __attribute__ ((aligned (PAGE_SIZE)));
+
+static inline void save_pg_dir(void)
+{
+ memcpy(swsusp_level4_pgt, init_level4_pgt, PAGE_SIZE);
+}
+#else
+static inline void save_pg_dir(void)
+{
+}
+#endif
+
/* Assumes all CPUs still execute in init_mm */
void zap_low_mappings(void)
{
- pgd_t *pgd = pgd_offset_k(0UL);
+ pgd_t *pgd;
+
+ save_pg_dir();
+
+ pgd = pgd_offset_k(0UL);
pgd_clear(pgd);
flush_tlb_all();
}