Changeset b5851913 in mainline


Ignore:
Timestamp:
2013-10-18T16:22:03Z (11 years ago)
Author:
Martin Decky <martin@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
a1314ce9
Parents:
0c96e6cb
Message:

fix kernel assertion (panic) on arm32 (BeagleBone and others) in frame_reference_add()

The macro PTE_GET_FRAME_ARCH() retrieves a physical frame number from the page table entry. Although the frame_base_addr member of the page table entry structure (pte_t) is declared as an unsigned bit field, due to the integer promotion rules the value is interpreted as a signed integer.

C99-§6.3.1.1: Boolean, characters, and integers

2: If an int can represent all values of the original type (as restricted by the width, for a bit-field), the value is converted to an int; otherwise, it is converted to an unsigned int. These are called the integer promotions. All other types are unchanged by the integer promotions.

Since the bitwise shift operations in PTE_GET_FRAME_ARCH() and especially in ADDR2PFN() (used by anon_share() in backend_anon.c) are applied on a signed integer, they create a false sign-extended (negative) physical frame number that is then passed to frame_reference_add(). This routine is obviously unable to find a valid physical memory zone for the malformed frame number and hits the assertion. The fix is to explicitly typecast the value in PTE_GET_FRAME_ARCH() as unsigned.

The original panic and stack trace for reference:

######> Kernel panic on cpu0 due to a failed assertion: <######
frame_reference_add() at generic/src/mm/frame.c:976:
znum != (size_t) -1

THE=0x802ca000: pe=1 thr=0x802c8000 task=0x802c1000 cpu=0x80292800
as=0x8000112c magic=0xfacefeed
0x802cbd2c: generic/src/debug/stacktrace.o:stack_trace()+0x0000001c
0x802cbd5c: generic/src/debug/panic.o:panic_common()+0x000001b4
0x802cbd94: generic/src/mm/frame.o:frame_reference_add()+0x000000a8
0x802cbdf4: generic/src/mm/backend_anon.o:anon_share()+0x00000168
0x802cbe44: generic/src/mm/as.o:as_area_share()+0x000001bc
0x802cbe7c: generic/src/ipc/ops/sharein.o:answer_preprocess()+0x0000007c
0x802cbeb4: generic/src/ipc/sysipc.o:answer_preprocess()+0x000000a4
0x802cbf04: generic/src/ipc/sysipc.o:sys_ipc_answer_fast()+0x0000007c
0x802cbf4c: generic/src/syscall/syscall.o:syscall_handler()+0x000000e0
0x802cbf74: arch/arm32/src/exception.o:swi_exception()+0x00000034
0x802cbfb4: generic/src/interrupt/interrupt.o:exc_dispatch()+0x00000144
cpu0: halted

Location:
kernel/arch/arm32/include/arch/mm
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • kernel/arch/arm32/include/arch/mm/page_armv4.h

    r0c96e6cb rb5851913  
    4848        (((pte_t *) (pte))->l0.descriptor_type != 0)
    4949#define PTE_GET_FRAME_ARCH(pte) \
    50         (((pte_t *) (pte))->l1.frame_base_addr << FRAME_WIDTH)
     50        (((uintptr_t) ((pte_t *) (pte))->l1.frame_base_addr) << FRAME_WIDTH)
    5151#define PTE_WRITABLE_ARCH(pte) \
    5252        (((pte_t *) (pte))->l1.access_permission_0 == PTE_AP_USER_RW_KERNEL_RW)
  • kernel/arch/arm32/include/arch/mm/page_armv6.h

    r0c96e6cb rb5851913  
    4848        (((pte_t *) (pte))->l0.descriptor_type != 0)
    4949#define PTE_GET_FRAME_ARCH(pte) \
    50         (((pte_t *) (pte))->l1.frame_base_addr << FRAME_WIDTH)
     50        (((uintptr_t) ((pte_t *) (pte))->l1.frame_base_addr) << FRAME_WIDTH)
    5151#define PTE_WRITABLE_ARCH(pte) \
    5252        (((pte_t *) (pte))->l1.access_permission_1 != PTE_AP1_RO)
Note: See TracChangeset for help on using the changeset viewer.