The Linux Channel :: Forum

define macro on kernel-space C code

Hi,
we see in the linux kernel code many macro, i see today this macros

http://elixir.free-electrons.com/linux/latest/source/arch/arm/mm/proc-v7-2level.S

#define TTB_S (1 << 1)
#define TTB_RGN_NC (0 << 3)
#define TTB_RGN_OC_WBWA (1 << 3)
#define TTB_RGN_OC_WT (2 << 3)
#define TTB_RGN_OC_WB (3 << 3)
#define TTB_NOS (1 << 5)
#define TTB_IRGN_NC ((0 << 0) | (0 << 6))
#define TTB_IRGN_WBWA ((0 << 0) | (1 << 6))
#define TTB_IRGN_WT ((1 << 0) | (0 << 6))
#define TTB_IRGN_WB ((1 << 0) | (1 << 6))


what means ((1 << 0) | (0 << 6)) here?

Tagged:

Comments

  • Hi Ramin,

    as you can see the complete code other than this part:
    /*
    * arch/arm/mm/proc-v7-2level.S
    *
    * Copyright (C) 2001 Deep Blue Solutions Ltd.
    *
    * This program is free software; you can redistribute it and/or modify
    * it under the terms of the GNU General Public License version 2 as
    * published by the Free Software Foundation.
    */

    #define TTB_S (1 << 1)
    #define TTB_RGN_NC (0 << 3)
    #define TTB_RGN_OC_WBWA (1 << 3)
    #define TTB_RGN_OC_WT (2 << 3)
    #define TTB_RGN_OC_WB (3 << 3)
    #define TTB_NOS (1 << 5)
    #define TTB_IRGN_NC ((0 << 0) | (0 << 6))
    #define TTB_IRGN_WBWA ((0 << 0) | (1 << 6))
    #define TTB_IRGN_WT ((1 << 0) | (0 << 6))
    #define TTB_IRGN_WB ((1 << 0) | (1 << 6))

    /* PTWs cacheable, inner WB not shareable, outer WB not shareable */
    #define TTB_FLAGS_UP TTB_IRGN_WB|TTB_RGN_OC_WB
    #define PMD_FLAGS_UP PMD_SECT_WB

    /* PTWs cacheable, inner WBWA shareable, outer WBWA not shareable */
    #define TTB_FLAGS_SMP TTB_IRGN_WBWA|TTB_S|TTB_NOS|TTB_RGN_OC_WBWA
    #define PMD_FLAGS_SMP PMD_SECT_WBWA|PMD_SECT_S

    They are trying to set (initialize flags).

    You can set flags with single unsigned char, or short, or a u32 (4 byte) data type.

    So a "<<" is a C bitwise operator doing left shift.
    https://en.wikipedia.org/wiki/Bitwise_operations_in_C

    For example:
    #define TTB_NOS (1 << 5)
    Which means a byte with 1 ==> [0000 0001] << 5 times
    Which gives you [0010 0000] which is 32 (in decimal).

    In that case you can use alternatively:
    #define TTB_NOS 32 but this tells #define TTB_NOS (1 << 5) clearly the bit
    set to 1 position within the flag.

    So there is another case:
    #define TTB_IRGN_WB ((1 << 0) | (1 << 6))
    which means [0000 0001] | [0100 0000]
    apply the "|" OR operation, then [0100 0001]
    which is 65 (in decimal).

    I just crudely calculated the derived values and the decimal equivalent values.

    But you can write a test user-space code and test these. Here is a code which I wrote to test
    these values:
    kiran@1TBWDBlueMobile:/code/temp$ vim test.c
    //The Linux Channel :: test arch/arm/mm/proc-v7-2level.S flags
    //Kiran - 9-may-2017

    #include <stdio.h>

    #define TTB_S (1 << 1)
    #define TTB_RGN_NC (0 << 3)
    #define TTB_RGN_OC_WBWA (1 << 3)
    #define TTB_RGN_OC_WT (2 << 3)
    #define TTB_RGN_OC_WB (3 << 3)
    #define TTB_NOS (1 << 5)
    #define TTB_IRGN_NC ((0 << 0) | (0 << 6))
    #define TTB_IRGN_WBWA ((0 << 0) | (1 << 6))
    #define TTB_IRGN_WT ((1 << 0) | (0 << 6))
    #define TTB_IRGN_WB ((1 << 0) | (1 << 6))

    void main()
    {
    printf("TTB_S -> %d\n", TTB_S);
    printf("TTB_RGN_NC -> %d\n", TTB_RGN_NC);
    printf("TTB_RGN_OC_WBWA -> %d\n", TTB_RGN_OC_WBWA);
    printf("TTB_RGN_OC_WT -> %d\n", TTB_RGN_OC_WT);
    printf("TTB_RGN_OC_WB -> %d\n", TTB_RGN_OC_WB);

    // ... and so on

    printf("TTB_IRGN_WT -> %d\n", TTB_IRGN_WT);
    printf("TTB_IRGN_WB -> %d\n", TTB_IRGN_WB);
    }
    kiran@1TBWDBlueMobile:/code/temp$ gcc -o test test.c
    kiran@1TBWDBlueMobile:/code/temp$ ./test
    TTB_S -> 2
    TTB_RGN_NC -> 0
    TTB_RGN_OC_WBWA -> 8
    TTB_RGN_OC_WT -> 16
    TTB_RGN_OC_WB -> 24
    TTB_IRGN_WT -> 1
    TTB_IRGN_WB -> 65
    kiran@1TBWDBlueMobile:/code/temp$


    Hope its clear :smile:

    cheers, Kiran


  • Also check this example, in which flags are defined. Looks bit different, but more or less same concept.


    http://elixir.free-electrons.com/linux/latest/source/include/linux/shm.h

    /* shm_mode upper byte flags */
    #define SHM_DEST 01000 /* segment will be destroyed on last detach */
    #define SHM_LOCKED 02000 /* segment will not be swapped */
    #define SHM_HUGETLB 04000 /* segment will use huge TLB pages */
    #define SHM_NORESERVE 010000 /* don't check for reservations */

    /* Bits [26:31] are reserved */

    /*
    * When SHM_HUGETLB is set bits [26:31] encode the log2 of the huge page size.
    * This gives us 6 bits, which is enough until someone invents 128 bit address
    * spaces.
    *
    * Assume these are all power of twos.
    * When 0 use the default page size.
    */
    #define SHM_HUGE_SHIFT 26
    #define SHM_HUGE_MASK 0x3f
    #define SHM_HUGE_2MB (21 << SHM_HUGE_SHIFT)
    #define SHM_HUGE_1GB (30 << SHM_HUGE_SHIFT)
  • Good answer! Thanks a lot,
Sign In or Register to comment.