On Wed, Sep 29, 2010 at 1:12 PM, Kostik Belousov <kostik...@gmail.com> wrote:
> On Wed, Sep 29, 2010 at 12:40:57PM -0700, Matthew Fleming wrote:
>> I'm hacking around with making a "fast reboot" that puts a copy of the
>> MBR from disk into address 0x7c00 and, after disabling various
>> translation bits and stopping other CPUs, branches to it, to skip the
>> hardware self test that normally happens on boot.
>>
>> I haven't gotten to the point of attempting to run the code at 0x7c00
>> because I'm first hitting a different error.  Despite my attempts to
>> enter a translation into the hardware page table, I get a panic trying
>> to write to address 0x7000, where I intended to put the trampoline
>> code that turns off translation.
>>
>> Rebooting...
>> Attempt to reset to MBR...
>> XXX attempting pmap_kenter()...
>> XXX copying bootstrap code...
>> panic @ time 1285760103.939, thread 0xffffff000775d960: Fatal trap 12:
>> page fault while in kernel mode
>>
>> cpuid = 0
>> Panic occurred in module kernel loaded at 0xffffffff80100000:
>>
>> Stack: --------------------------------------------------
>> kernel:trap_fatal+0xac
>> kernel:trap_pfault+0x24c
>> kernel:trap+0x42e
>> kernel:bcopy+0x16
>> kernel:shutdown_reset+0x48
>> kernel:boot+0x317
>> kernel:reboot+0x60
>> kernel:ia32_syscall+0x1cd
>> --------------------------------------------------
>> cpuid = 0; apic id = 00
>> fault virtual address   = 0x7000
>> fault code              = supervisor write data, page not present
>> stack pointer           = 0x10:0xffffff8059e07670
>> frame pointer           = 0x10:0xffffff8059e07780
>>
>> Here's what I think is the relevant snippets of code.  Note that I
>> reserved the vm_page_t for physical page 7 as mbr_page early in boot,
>> so I know the memory is free.
>>
>> void
>> pmap_kenter_VR(vm_paddr_t pa)
>> {
>>       pmap_t pmap = kernel_pmap;
>>       vm_page_t mpte;
>>       pd_entry_t *pde;
>>       pt_entry_t *pte;
>>
>>       vm_page_lock_queues();
>>       PMAP_LOCK(pmap);
>>       mpte = pmap_allocpte(pmap, pa, M_WAITOK);
>>
>>       pde = pmap_pde(pmap, pa);
>>       if (pde == NULL || (*pde & PG_V) == 0)
>>               panic("%s: invalid page directory va=%#lx", __func__, pa);
>>       if ((*pde & PG_PS) != 0)
>>               panic("%s: attempted pmap_enter on 2MB page", __func__);
>>       pte = pmap_pde_to_pte(pde, pa);
>>       if (pte == NULL)
>>               panic("%s: no pte va=%#lx", __func__, pa);
>>
>>       if (*pte != 0) {
>>               /* Remove extra pte reference. */
>>               mpte->wire_count--;
>>       }
>>         pte_store(pte, pa | PG_RW | PG_V | PG_G | pg_nx);
>>
>>       vm_page_unlock_queues();
>>       PMAP_UNLOCK(pmap);
>> }
>>
>> Then in cpu_reset():
>>
>>       /*
>>        * Establish a V=R mapping for the MBR page, and copy a
>>        * reasonable guess at the size of the bootstrap code into the
>>        * beginning of the page.
>>        */
>>       printf("XXX attempting pmap_kenter()...\n");
>>       pmap_kenter_VR(trunc_page(mbaddr));
>>       printf("XXX copying bootstrap code...\n");
>>       to_copy = (uintptr_t)xxx_reset_end - (uintptr_t)xxx_reset_real;
>>       if (to_copy > mbaddr - trunc_page(mbaddr))
>>               to_copy = mbaddr - trunc_page(mbaddr);
>>       bcopy(xxx_reset_real, (void *)trunc_page(mbaddr), to_copy);  /* die 
>> here */
>>       printf("XXX attempting to turn off xlation and re-run MBR...\n");
>>       xxx_reset_real(mbaddr);
>>
>>
>> My first attempt was a call to
>>       pmap_kenter(trunc_page(0x7c00), trunc_page(0x7c00));
>> which failed trying to dereference the non-existent PDE.
>>
>> My second attempt called
>>       pmap_enter(kernel_pmap, trunc_page(0x7c00), VM_PROT_WRITE, mbr_page,
>>           VM_PROT_ALL, 0);
>> That failed with the same crash as the attempt using pmap_kenter_VR().
>>
>> So... any thoughts as to why, after an apparently successful
>> installation of an xlation, I still get a panic as though there were
>> no xlation?
>
> Weird formatting of backtrace. Is this some proprietary code ?

Yeah, there's some Isilon local modifications.

> Why do you try to create 1-1 mapping at all ? The MBR code should be
> executing in real mode anyway, and the mapping address at the moment of
> bcopy does not matter at all. I think that the use of PHYS_TO_DMAP()
> should give you direct mapping.

I assumed I need trampoline code.  The moment I turn off the xlation
bits, if the instruction pointer I'm running from is the normal kernel
addresses, won't I die horribly trying to access 0xffffffff80000000 or
so in real mode?

> About the #pf that you see. I think that this is due to the fact that
> you are modifying kernel pmap, while the active one is the pmap of
> the user process which context issued reboot().

Isn't the kernel pmap active in the kernel, since I've entered via the
syscall reboot(2) ?

Thanks,
matthew
_______________________________________________
freebsd-hackers@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-hackers
To unsubscribe, send any mail to "freebsd-hackers-unsubscr...@freebsd.org"

Reply via email to