Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Pal/Linux-SGX] EDMM hybrid allocation #1262

Open
wants to merge 8 commits into
base: master
Choose a base branch
from

Conversation

vijaydhanraj
Copy link
Contributor

@vijaydhanraj vijaydhanraj commented Mar 31, 2023

Description of the changes

To reduce the enclave exits, pre-allocate minimal heap from top as required by application and allocate the remaining dynamically using EDMM. As part of this commit, introduced a new manifest option sgx.edmm_heap_prealloc_size to pre-allocate amount of heap required by the application.

Note: This change assumes there is a single heap region (also called "free") that is beneath all other statically allocated memory areas (manifest, ssa, tls. tcs, stack, sig_stack, pal).

Sample memory regions with helloworld program

000000000fffc000-0000000010000000 manifest
000000000ff7c000-000000000fffc000 ssa
000000000ff6c000-000000000ff7c000 tcs
000000000ff5c000-000000000ff6c000 tls
000000000ff1c000-000000000ff5c000 stack
000000000fedc000-000000000ff1c000 stack
000000000fe9c000-000000000fedc000 stack
000000000fe5c000-000000000fe9c000 stack
000000000fe1c000-000000000fe5c000 stack
000000000fddc000-000000000fe1c000 stack
000000000fd9c000-000000000fddc000 stack
000000000fd5c000-000000000fd9c000 stack
000000000fd1c000-000000000fd5c000 stack
000000000fcdc000-000000000fd1c000 stack
000000000fc9c000-000000000fcdc000 stack
000000000fc5c000-000000000fc9c000 stack
000000000fc1c000-000000000fc5c000 stack
000000000fbdc000-000000000fc1c000 stack
000000000fb9c000-000000000fbdc000 stack
000000000fb5c000-000000000fb9c000 stack
000000000fb4c000-000000000fb5c000 sig_stack
000000000fb3c000-000000000fb4c000 sig_stack
000000000fb2c000-000000000fb3c000 sig_stack
000000000fb1c000-000000000fb2c000 sig_stack
000000000fb0c000-000000000fb1c000 sig_stack
000000000fafc000-000000000fb0c000 sig_stack
000000000faec000-000000000fafc000 sig_stack
000000000fadc000-000000000faec000 sig_stack
000000000facc000-000000000fadc000 sig_stack
000000000fabc000-000000000facc000 sig_stack
000000000faac000-000000000fabc000 sig_stack
000000000fa9c000-000000000faac000 sig_stack
000000000fa8c000-000000000fa9c000 sig_stack
000000000fa7c000-000000000fa8c000 sig_stack
000000000fa6c000-000000000fa7c000 sig_stack
000000000fa5c000-000000000fa6c000 sig_stack
000000000f9f5000-000000000fa5c000 pal
0000000000010000-000000000f9f5000 free

Fixes #1221

How to test this PR?

Regular EDMM CI pipeline with sgx.edmm_heap_prealloc_size.
Note: Currently the default value for sgx.edmm_heap_prealloc_size is set to zero. Based on experiments, need to set this to a reasonable default.


This change is Reviewable

To reduce the enclave exits, pre-allocate minimal heap from top
as required by application and allocate the remaining dynamically
using EDMM. As part of this commit, introduced a new manifest
option `sgx.edmm_heap_prealloc_size` to pre-allocate amount of
heap required by the application.

Note: This change assumes there is a single heap region (also
called "free") that is beneath all other statically allocated
memory areas (manifest, ssa, tls. tcs, stack, sig_stack, pal).

Sample memory regions with helloworld program
000000000fffc000-0000000010000000 manifest
000000000ff7c000-000000000fffc000 ssa
000000000ff6c000-000000000ff7c000 tcs
000000000ff5c000-000000000ff6c000 tls
000000000ff1c000-000000000ff5c000 stack
000000000fedc000-000000000ff1c000 stack
000000000fe9c000-000000000fedc000 stack
000000000fe5c000-000000000fe9c000 stack
000000000fe1c000-000000000fe5c000 stack
000000000fddc000-000000000fe1c000 stack
000000000fd9c000-000000000fddc000 stack
000000000fd5c000-000000000fd9c000 stack
000000000fd1c000-000000000fd5c000 stack
000000000fcdc000-000000000fd1c000 stack
000000000fc9c000-000000000fcdc000 stack
000000000fc5c000-000000000fc9c000 stack
000000000fc1c000-000000000fc5c000 stack
000000000fbdc000-000000000fc1c000 stack
000000000fb9c000-000000000fbdc000 stack
000000000fb5c000-000000000fb9c000 stack
000000000fb4c000-000000000fb5c000 sig_stack
000000000fb3c000-000000000fb4c000 sig_stack
000000000fb2c000-000000000fb3c000 sig_stack
000000000fb1c000-000000000fb2c000 sig_stack
000000000fb0c000-000000000fb1c000 sig_stack
000000000fafc000-000000000fb0c000 sig_stack
000000000faec000-000000000fafc000 sig_stack
000000000fadc000-000000000faec000 sig_stack
000000000facc000-000000000fadc000 sig_stack
000000000fabc000-000000000facc000 sig_stack
000000000faac000-000000000fabc000 sig_stack
000000000fa9c000-000000000faac000 sig_stack
000000000fa8c000-000000000fa9c000 sig_stack
000000000fa7c000-000000000fa8c000 sig_stack
000000000fa6c000-000000000fa7c000 sig_stack
000000000fa5c000-000000000fa6c000 sig_stack
000000000f9f5000-000000000fa5c000 pal
0000000000010000-000000000f9f5000 free

Signed-off-by: Vijay Dhanraj <vijay.dhanraj@intel.com>
Copy link
Contributor Author

@vijaydhanraj vijaydhanraj left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewable status: 0 of 12 files reviewed, 2 unresolved discussions, not enough approvals from maintainers (3 more required), not enough approvals from different teams (2 more required, approved so far: )


pal/src/host/linux-sgx/enclave_edmm.c line 82 at r1 (raw file):

            /* Entire request is in pre-allocated range, so clear memory to mimic SGX2 allocation */
            if (pre_allocated_count == original_count) {
                memset((void*)addr, 0, (pre_allocated_count * PAGE_SIZE));

SGX2 EAUG instruction zeroes EPC page and so added this memset to zero the memory for the pre-allocated heap which is not added dynamically.


python/graminelibos/sgx_sign.py line 306 at r1 (raw file):

    free_areas = []
    for area in areas:
        addr = area.addr + area.size

This seems to be a like a dead code and so I have added a new function check_memory_area_holes to check there are no holes between memory regions. If maintainers agree, I can remove this code either as part of this PR or can create a new PR.

Copy link

@dimakuv dimakuv left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed 12 of 12 files at r1, all commit messages.
Reviewable status: all files reviewed, 50 unresolved discussions, not enough approvals from maintainers (3 more required), not enough approvals from different teams (2 more required, approved so far: ) (waiting on @vijaydhanraj)

a discussion (no related file):

Note: Currently the default value for sgx.edmm_heap_prealloc_size is set to zero. Based on experiments, need to set this to a reasonable default.

We should do this in some follow-up PR, after a lot of testing and deciding on the "good enough" value.

For now, having a default of 0 seems reasonable -- as if this feature is not enabled at all.



-- commits line 2 at r1:
Introduce .... We can fix it during final rebase.


-- commits line 2 at r1:
Also, do we want to mention hybrid here? The term is a bit vague. Maybe "EDMM pre-allocation of part of heap"?


-- commits line 8 at r1:
This needs slight rewording (remove the, minimal -> some amount of, introduced- > introduce, etc). This can be done during final rebase.


-- commits line 8 at r1:
I would also add a sentence: Currently the default value is zero. This may be changed in future commits, based on perf experiments.


-- commits line 12 at r1:
. -> ,


-- commits line 52 at r1:
This list doesn't belong to the commit message. You already have the note here, and the example is meaningless (it's enough to have it in the PR description). So we'll remove this during final rebase.


Documentation/manifest-syntax.rst line 486 at r1 (raw file):

   Support for EDMM first appeared in Linux 6.0.

EDMM Hybrid allocation (Experimental)

Hybrid -> hybrid (no need for capital letter)


Documentation/manifest-syntax.rst line 486 at r1 (raw file):

   Support for EDMM first appeared in Linux 6.0.

EDMM Hybrid allocation (Experimental)

Why do we mark it as experimental? I think we could remove this.


Documentation/manifest-syntax.rst line 495 at r1 (raw file):

When ``sgx.edmm_enable`` is enabled, users can precisely set the amount of heap
to pre-allocate by setting the ``sgx.edmm_heap_prealloc_size``. For

by setting this option


Documentation/manifest-syntax.rst line 496 at r1 (raw file):

When ``sgx.edmm_enable`` is enabled, users can precisely set the amount of heap
to pre-allocate by setting the ``sgx.edmm_heap_prealloc_size``. For
example, when size is set to "64M" Gramine will pre-allocate top 64M of heap

Please remove top, this is an internal Gramine detail (that Gramine allocates heap pages starting from the top, so we need to also preallocate starting from the top here). Users don't need to know about this.


Documentation/manifest-syntax.rst line 497 at r1 (raw file):

to pre-allocate by setting the ``sgx.edmm_heap_prealloc_size``. For
example, when size is set to "64M" Gramine will pre-allocate top 64M of heap
pages rather than allocating dynamically and thus the name "Hybrid allocation".

I would remove this and thus the name .... This doesn't add any information.


Documentation/manifest-syntax.rst line 498 at r1 (raw file):

example, when size is set to "64M" Gramine will pre-allocate top 64M of heap
pages rather than allocating dynamically and thus the name "Hybrid allocation".
This may help to balance out the cost between load time and run time.

I think this sentence should be replaced with a more specific one: Higher values in this option improve run time but worsen startup time, and vice versa.


Documentation/manifest-syntax.rst line 841 at r1 (raw file):

large enough to hold the whole heap area.

This option is invalid (i.e. must be ``false``) when only ``sgx.edmm_enable``is

Please add a space before is


Documentation/manifest-syntax.rst line 843 at r1 (raw file):

This option is invalid (i.e. must be ``false``) when only ``sgx.edmm_enable``is
specified, as there are no heap pages to pre-fault. But if used together with
``sgx.edmm_heap_prealloc_size``, then the pre-allocated heap size will be

I would remove the word size here, as it reads like broken English to me.


Documentation/manifest-syntax.rst line 844 at r1 (raw file):

specified, as there are no heap pages to pre-fault. But if used together with
``sgx.edmm_heap_prealloc_size``, then the pre-allocated heap size will be
pre-faulted.

I would add also (i.e., ... will also be pre-faulted.)


pal/src/host/linux-sgx/enclave_edmm.c line 35 at r1 (raw file):

/* Returns page count that is non overlapping with the pre-allocated heap. 0 means entire request
 * overlaps with the pre-allocated region.
 * Partial overlap illustration:

Rewording:

/* Updates page count such that the request is fully below the pre-allocated heap.
 * If `count` is updated to 0, then the entire request overlaps with pre-allocated heap.
 *

pal/src/host/linux-sgx/enclave_edmm.c line 45 at r1 (raw file):

    addr    <-----+         |
                  |         |
                  +---------+

Here is my ASCII kung-fu:

                +----------------------+ --> heap_max
                |                      |
addr + size <-- |  Pre-allocated heap  |
                |                      |
                +----------------------+ --> edmm_heap_prealloc_start
                |                      |     (heap_max + edmm_heap_prealloc_size)
                |  Dynamically         |
       addr <-- |  allocated heap      |
                |                      |
                +----------------------+


pal/src/host/linux-sgx/enclave_edmm.c line 62 at r1 (raw file):

    } else {
        /* No overlap: Return the original count */
    }

I think this way is easier to read:

    if (addr >= edmm_heap_prealloc_start) {
        /* full overlap: entire request lies in the pre-allocated region */
        *count = 0;
    } else if (addr + size > edmm_heap_prealloc_start) {
        /* partial overlap: update count to skip the pre-allocated region */
        *count = (edmm_heap_prealloc_start - addr) / PAGE_SIZE;
    } else {
        /* no overlap: don't update count */
    }
}

pal/src/host/linux-sgx/enclave_edmm.c line 73 at r1 (raw file):

    }

    /* Update count with preallocated heap */

Remove this sentence, it's obvious what happens (from variable names and function names)


pal/src/host/linux-sgx/enclave_edmm.c line 78 at r1 (raw file):

        exclude_preallocated_pages(addr, &count);

        size_t pre_allocated_count = original_count - count;

Please rename to preallocated_count


pal/src/host/linux-sgx/enclave_edmm.c line 84 at r1 (raw file):

                memset((void*)addr, 0, (pre_allocated_count * PAGE_SIZE));
                return 0;
            }

This is hard to read. This looks simpler:

        if (count == 0) {
            /* entire request is in pre-allocated range */
            memset((void*)addr, 0, (preallocated_count * PAGE_SIZE));
            return 0;
        }

       /* request is partially in pre-allocated range */
      memset((void*)(addr + count * PAGE_SIZE), 0, pre_allocated_count * PAGE_SIZE);

pal/src/host/linux-sgx/enclave_edmm.c line 88 at r1 (raw file):

            /* Partial request is part of the pre-allocated range, so just clear memory contents in
             * the pre-allocated range to mimic SGX2 allocation */
            memset((void*)(addr + (count * PAGE_SIZE)), 0, (pre_allocated_count * PAGE_SIZE));

Too long comment and too many braces. See my code snippet above.


pal/src/host/linux-sgx/enclave_edmm.c line 138 at r1 (raw file):

int sgx_edmm_remove_pages(uint64_t addr, size_t count) {
    /* Update count with preallocated heap */

Please remove this comment


pal/src/host/linux-sgx/host_main.c line 719 at r1 (raw file):

    }

    if (!enclave_info->edmm_enabled && enclave_info->edmm_heap_prealloc_size > 0) {

Why do you need these two checks here (in untrusted PAL) if you have the same checks in trusted PAL? I suggest to remove these two checks from here and keep them only in the trusted PAL.


pal/src/host/linux-sgx/host_main.c line 720 at r1 (raw file):

    if (!enclave_info->edmm_enabled && enclave_info->edmm_heap_prealloc_size > 0) {
        log_error("sgx.edmm_heap_prealloc_size should be used along with sgx.edmm_enable!");

should -> must

along -> together


pal/src/host/linux-sgx/host_main.c line 720 at r1 (raw file):

    if (!enclave_info->edmm_enabled && enclave_info->edmm_heap_prealloc_size > 0) {
        log_error("sgx.edmm_heap_prealloc_size should be used along with sgx.edmm_enable!");

Please put both manifest options in ''


pal/src/host/linux-sgx/host_main.c line 726 at r1 (raw file):

    if (!IS_ALIGNED(enclave_info->edmm_heap_prealloc_size, g_page_size)) {
        log_error("edmm_heap_prealloc_size should be page aligned: %ld", g_page_size);

Please add 'sgx.'


pal/src/host/linux-sgx/host_main.c line 726 at r1 (raw file):

    if (!IS_ALIGNED(enclave_info->edmm_heap_prealloc_size, g_page_size)) {
        log_error("edmm_heap_prealloc_size should be page aligned: %ld", g_page_size);

I see no point in printing the g_page_size variable.

Maybe just print a message with ...must be 4K (page) aligned?


pal/src/host/linux-sgx/pal_main.c line 532 at r1 (raw file):

static void do_preheat_enclave(void) {
    /* Heap allocation requests are serviced starting from highest heap address. So when
     * sgx.edmm_heap_prealloc_size is turned on preheat from the top of the heap until

Add a comma after turned on


pal/src/host/linux-sgx/pal_main.c line 582 at r1 (raw file):

    if (!edmm_enabled && edmm_heap_prealloc_size > 0) {
        log_error("edmm_heap_prealloc_size should be used along with edmm_enabled!");

ditto


pal/src/host/linux-sgx/pal_main.c line 588 at r1 (raw file):

    size_t total_heap_size = g_pal_linuxsgx_state.heap_max - g_pal_linuxsgx_state.heap_min;
    if (edmm_heap_prealloc_size > total_heap_size) {
        log_error("edmm_heap_prealloc_size should be less than total heap size 0x%lx",

ditto


pal/src/host/linux-sgx/pal_main.c line 775 at r1 (raw file):

        if (g_pal_linuxsgx_state.edmm_enabled && !g_pal_linuxsgx_state.edmm_heap_prealloc_size) {
            log_error("'sgx.preheat_enclave' manifest option makes no sense with only EDMM enabled."
                        " Need to enable edmm_heap_prealloc_size as well!");

Wrong indentation


pal/src/host/linux-sgx/pal_main.c line 775 at r1 (raw file):

        if (g_pal_linuxsgx_state.edmm_enabled && !g_pal_linuxsgx_state.edmm_heap_prealloc_size) {
            log_error("'sgx.preheat_enclave' manifest option makes no sense with only EDMM enabled."
                        " Need to enable edmm_heap_prealloc_size as well!");

I don't think you want users to force to enable this new manifest option (that's how your current sentence reads). Maybe simply:

'sgx.preheat_enclave' manifest option makes no sense with EDMM enabled
and 'sgx.edmm_heap_prealloc_size' equal to zero!

python/graminelibos/sgx_sign.py line 284 at r1 (raw file):

    gen_area_content(attr, areas, enclave_base, enclave_heap_min)

    # Enclaves with EDMM do not add "free" memory at startup but if heap is pre-allocated

Please add a , before but


python/graminelibos/sgx_sign.py line 285 at r1 (raw file):

    # Enclaves with EDMM do not add "free" memory at startup but if heap is pre-allocated
    # using manifest `sgx.edmm_heap_prealloc_size` add the "free" pre-allocated pages.

Remove manifest word


python/graminelibos/sgx_sign.py line 285 at r1 (raw file):

    # Enclaves with EDMM do not add "free" memory at startup but if heap is pre-allocated
    # using manifest `sgx.edmm_heap_prealloc_size` add the "free" pre-allocated pages.

add -> then


python/graminelibos/sgx_sign.py line 286 at r1 (raw file):

    # Enclaves with EDMM do not add "free" memory at startup but if heap is pre-allocated
    # using manifest `sgx.edmm_heap_prealloc_size` add the "free" pre-allocated pages.
    # PS: Assumption here is that we have a single heap region (called "free") that is beneath all

Remove PS:. Also, add an empty comment line to visually separate these two sentences.


python/graminelibos/sgx_sign.py line 291 at r1 (raw file):

        free_preallocated = []
        if (attr['edmm_heap_prealloc_size'] > 0 and
                last_populated_addr > enclave_heap_min):

Doesn't it fit into 100 chars per line? Also, no need for ()


python/graminelibos/sgx_sign.py line 291 at r1 (raw file):

        free_preallocated = []
        if (attr['edmm_heap_prealloc_size'] > 0 and
                last_populated_addr > enclave_heap_min):

Why do you compare last_populated_addr against enclave_heap_min? Shouldn't it be attr['edmm_heap_prealloc_size']?


python/graminelibos/sgx_sign.py line 292 at r1 (raw file):

        if (attr['edmm_heap_prealloc_size'] > 0 and
                last_populated_addr > enclave_heap_min):

Please remove empty line


python/graminelibos/sgx_sign.py line 293 at r1 (raw file):

                last_populated_addr > enclave_heap_min):

            flags = PAGEINFO_R | PAGEINFO_W | PAGEINFO_X | PAGEINFO_REG

Oops, this is a security problem! When we use sgx.edmm_heap_prealloc_size, the pre-allocated range necessarily has RWX permissions. We should at least mention it in the documentation... I have no ideas how to solve it (if at all possible).

I didn't think of it before, but it's interesting: with this hybrid allocation, we trade security for performance. We kinda "drag" the SGXv1 page-permissions problem into the top part of the heap here.


python/graminelibos/sgx_sign.py line 296 at r1 (raw file):

            start_addr = last_populated_addr - attr['edmm_heap_prealloc_size']
            if start_addr < enclave_heap_min:
                raise Exception(" sgx.edmm_heap_prealloc_size cannot be more than total heap size!")

I would re-rephase like: sgx.edmm_heap_prealloc_size is greater than total heap size!


python/graminelibos/sgx_sign.py line 306 at r1 (raw file):

Previously, vijaydhanraj (Vijay Dhanraj) wrote…

This seems to be a like a dead code and so I have added a new function check_memory_area_holes to check there are no holes between memory regions. If maintainers agree, I can remove this code either as part of this PR or can create a new PR.

I'd prefer a separate PR.


python/graminelibos/sgx_sign.py line 468 at r1 (raw file):

            return 1
        last_populated_addr = area.addr

This function is so small and simple -- I wouldn't use empty lines here


python/graminelibos/sgx_sign.py line 469 at r1 (raw file):

        last_populated_addr = area.addr

    return 0

This should return True and False


python/graminelibos/sgx_sign.py line 489 at r1 (raw file):

    if not attr['edmm_enable'] and attr['edmm_heap_prealloc_size'] > 0:
        raise Exception("sgx.edmm_heap_prealloc_size should be used along with sgx.edmm_enable!")

should -> must

along -> together


python/graminelibos/sgx_sign.py line 494 at r1 (raw file):

       is_aligned(attr['edmm_heap_prealloc_size'], offs.PAGESIZE) == 0:
        raise Exception("sgx.edmm_heap_prealloc_size: {0} should be greater than or equal to 0!"
                        .format(attr['edmm_heap_prealloc_size']))

I suggest to remove this whole IF. I don't think the Python code must have such checks, that's just too much hand-holding of manifest writers.


python/graminelibos/sgx_sign.py line 536 at r1 (raw file):

    memory_areas = populate_memory_areas(attr, memory_areas, enclave_base, enclave_heap_min)

    # Ensure no holes in the populated memory areas

The comment looks redundant, please remove


python/graminelibos/sgx_sign.py line 539 at r1 (raw file):

    memory_area_holes = check_memory_area_holes(attr, memory_areas, enclave_base)
    if memory_area_holes:
        raise Exception('Cannot have holes in memory areas!')

in enclave memory areas

Copy link
Contributor Author

@vijaydhanraj vijaydhanraj left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewable status: 7 of 12 files reviewed, 50 unresolved discussions, not enough approvals from maintainers (3 more required), not enough approvals from different teams (2 more required, approved so far: ), "fixup! " found in commit messages' one-liners (waiting on @dimakuv)


-- commits line 2 at r1:

Previously, dimakuv (Dmitrii Kuvaiskii) wrote…

Also, do we want to mention hybrid here? The term is a bit vague. Maybe "EDMM pre-allocation of part of heap"?

How about Introduce EDMM pre-allocated heap optimization?


-- commits line 2 at r1:

Previously, dimakuv (Dmitrii Kuvaiskii) wrote…

Introduce .... We can fix it during final rebase.

ok, thanks.


-- commits line 8 at r1:

Previously, dimakuv (Dmitrii Kuvaiskii) wrote…

This needs slight rewording (remove the, minimal -> some amount of, introduced- > introduce, etc). This can be done during final rebase.

ok, thanks.


-- commits line 8 at r1:

Previously, dimakuv (Dmitrii Kuvaiskii) wrote…

I would also add a sentence: Currently the default value is zero. This may be changed in future commits, based on perf experiments.

sure, can you please fix this as part of the final rebase?


-- commits line 12 at r1:

Previously, dimakuv (Dmitrii Kuvaiskii) wrote…

. -> ,

Can you please fix this as part of the final rebase?


-- commits line 52 at r1:

Previously, dimakuv (Dmitrii Kuvaiskii) wrote…

This list doesn't belong to the commit message. You already have the note here, and the example is meaningless (it's enough to have it in the PR description). So we'll remove this during final rebase.

ok, thanks.


Documentation/manifest-syntax.rst line 486 at r1 (raw file):

Previously, dimakuv (Dmitrii Kuvaiskii) wrote…

Hybrid -> hybrid (no need for capital letter)

Done but should we rename this EDMM pre-allocate heap?


Documentation/manifest-syntax.rst line 486 at r1 (raw file):

Previously, dimakuv (Dmitrii Kuvaiskii) wrote…

Why do we mark it as experimental? I think we could remove this.

Done.


Documentation/manifest-syntax.rst line 495 at r1 (raw file):

Previously, dimakuv (Dmitrii Kuvaiskii) wrote…

by setting this option

Done.


Documentation/manifest-syntax.rst line 496 at r1 (raw file):

Previously, dimakuv (Dmitrii Kuvaiskii) wrote…

Please remove top, this is an internal Gramine detail (that Gramine allocates heap pages starting from the top, so we need to also preallocate starting from the top here). Users don't need to know about this.

Done.


Documentation/manifest-syntax.rst line 497 at r1 (raw file):

Previously, dimakuv (Dmitrii Kuvaiskii) wrote…

I would remove this and thus the name .... This doesn't add any information.

Done.


Documentation/manifest-syntax.rst line 498 at r1 (raw file):

Previously, dimakuv (Dmitrii Kuvaiskii) wrote…

I think this sentence should be replaced with a more specific one: Higher values in this option improve run time but worsen startup time, and vice versa.

Done with minor rewording. The following is the current text,

When ``sgx.edmm_enable`` is enabled, users can precisely set the amount of heap to pre-allocate by setting this option. For example, when size is set to "64M" Gramine will pre-allocate 64M of heap pages to the enclave (similar to SGXv1) rather than allocating dynamically them. Higher values in this option may improve run time but could worsen startup time, and vice versa.


Documentation/manifest-syntax.rst line 841 at r1 (raw file):

Previously, dimakuv (Dmitrii Kuvaiskii) wrote…

Please add a space before is

Done.


Documentation/manifest-syntax.rst line 843 at r1 (raw file):

Previously, dimakuv (Dmitrii Kuvaiskii) wrote…

I would remove the word size here, as it reads like broken English to me.

Done.


Documentation/manifest-syntax.rst line 844 at r1 (raw file):

Previously, dimakuv (Dmitrii Kuvaiskii) wrote…

I would add also (i.e., ... will also be pre-faulted.)

Done.


pal/src/host/linux-sgx/enclave_edmm.c line 35 at r1 (raw file):

Previously, dimakuv (Dmitrii Kuvaiskii) wrote…

Rewording:

/* Updates page count such that the request is fully below the pre-allocated heap.
 * If `count` is updated to 0, then the entire request overlaps with pre-allocated heap.
 *

Done.


pal/src/host/linux-sgx/enclave_edmm.c line 45 at r1 (raw file):

Previously, dimakuv (Dmitrii Kuvaiskii) wrote…

Here is my ASCII kung-fu:

                +----------------------+ --> heap_max
                |                      |
addr + size <-- |  Pre-allocated heap  |
                |                      |
                +----------------------+ --> edmm_heap_prealloc_start
                |                      |     (heap_max + edmm_heap_prealloc_size)
                |  Dynamically         |
       addr <-- |  allocated heap      |
                |                      |
                +----------------------+

Done.


pal/src/host/linux-sgx/enclave_edmm.c line 62 at r1 (raw file):

Previously, dimakuv (Dmitrii Kuvaiskii) wrote…

I think this way is easier to read:

    if (addr >= edmm_heap_prealloc_start) {
        /* full overlap: entire request lies in the pre-allocated region */
        *count = 0;
    } else if (addr + size > edmm_heap_prealloc_start) {
        /* partial overlap: update count to skip the pre-allocated region */
        *count = (edmm_heap_prealloc_start - addr) / PAGE_SIZE;
    } else {
        /* no overlap: don't update count */
    }
}

Done.


pal/src/host/linux-sgx/enclave_edmm.c line 73 at r1 (raw file):

Previously, dimakuv (Dmitrii Kuvaiskii) wrote…

Remove this sentence, it's obvious what happens (from variable names and function names)

Done.


pal/src/host/linux-sgx/enclave_edmm.c line 78 at r1 (raw file):

Previously, dimakuv (Dmitrii Kuvaiskii) wrote…

Please rename to preallocated_count

Done.


pal/src/host/linux-sgx/enclave_edmm.c line 84 at r1 (raw file):

Previously, dimakuv (Dmitrii Kuvaiskii) wrote…

This is hard to read. This looks simpler:

        if (count == 0) {
            /* entire request is in pre-allocated range */
            memset((void*)addr, 0, (preallocated_count * PAGE_SIZE));
            return 0;
        }

       /* request is partially in pre-allocated range */
      memset((void*)(addr + count * PAGE_SIZE), 0, pre_allocated_count * PAGE_SIZE);

OK, done.


pal/src/host/linux-sgx/enclave_edmm.c line 88 at r1 (raw file):

Previously, dimakuv (Dmitrii Kuvaiskii) wrote…

Too long comment and too many braces. See my code snippet above.

Done.


pal/src/host/linux-sgx/enclave_edmm.c line 138 at r1 (raw file):

Previously, dimakuv (Dmitrii Kuvaiskii) wrote…

Please remove this comment

Done.


pal/src/host/linux-sgx/host_main.c line 719 at r1 (raw file):

Previously, dimakuv (Dmitrii Kuvaiskii) wrote…

Why do you need these two checks here (in untrusted PAL) if you have the same checks in trusted PAL? I suggest to remove these two checks from here and keep them only in the trusted PAL.

Added the checks in the untrusted PAL because, it here that we EADD the pages to enclave (as part of initialize_enclave()). Any incorrect values may result in EADD failing and it may not be clear why it failed.


pal/src/host/linux-sgx/host_main.c line 720 at r1 (raw file):

Previously, dimakuv (Dmitrii Kuvaiskii) wrote…

should -> must

along -> together

Done.

Code quote:

sgx.edmm_heap_prealloc_size should be used along with sgx.edmm_enable!

pal/src/host/linux-sgx/host_main.c line 720 at r1 (raw file):

Previously, dimakuv (Dmitrii Kuvaiskii) wrote…

Please put both manifest options in ''

Done.


pal/src/host/linux-sgx/host_main.c line 726 at r1 (raw file):

Previously, dimakuv (Dmitrii Kuvaiskii) wrote…

Please add 'sgx.'

Done.


pal/src/host/linux-sgx/host_main.c line 726 at r1 (raw file):

Previously, dimakuv (Dmitrii Kuvaiskii) wrote…

I see no point in printing the g_page_size variable.

Maybe just print a message with ...must be 4K (page) aligned?

Done.


pal/src/host/linux-sgx/pal_main.c line 532 at r1 (raw file):

Previously, dimakuv (Dmitrii Kuvaiskii) wrote…

Add a comma after turned on

Done.


pal/src/host/linux-sgx/pal_main.c line 582 at r1 (raw file):

Previously, dimakuv (Dmitrii Kuvaiskii) wrote…

ditto

Done.


pal/src/host/linux-sgx/pal_main.c line 588 at r1 (raw file):

Previously, dimakuv (Dmitrii Kuvaiskii) wrote…

ditto

Done.


pal/src/host/linux-sgx/pal_main.c line 775 at r1 (raw file):

Previously, dimakuv (Dmitrii Kuvaiskii) wrote…

Wrong indentation

Done.


pal/src/host/linux-sgx/pal_main.c line 775 at r1 (raw file):

Previously, dimakuv (Dmitrii Kuvaiskii) wrote…

I don't think you want users to force to enable this new manifest option (that's how your current sentence reads). Maybe simply:

'sgx.preheat_enclave' manifest option makes no sense with EDMM enabled
and 'sgx.edmm_heap_prealloc_size' equal to zero!

Done.


python/graminelibos/sgx_sign.py line 284 at r1 (raw file):

Previously, dimakuv (Dmitrii Kuvaiskii) wrote…

Please add a , before but

Done.


python/graminelibos/sgx_sign.py line 285 at r1 (raw file):

Previously, dimakuv (Dmitrii Kuvaiskii) wrote…

Remove manifest word

Done.


python/graminelibos/sgx_sign.py line 285 at r1 (raw file):

Previously, dimakuv (Dmitrii Kuvaiskii) wrote…

add -> then

you mean to add then before add? Something like below?

    # Enclaves with EDMM do not add "free" memory at startup, but if heap is pre-allocated
    # using `sgx.edmm_heap_prealloc_size` then add the "free" pre-allocated pages.

python/graminelibos/sgx_sign.py line 286 at r1 (raw file):

Previously, dimakuv (Dmitrii Kuvaiskii) wrote…

Remove PS:. Also, add an empty comment line to visually separate these two sentences.

Done.


python/graminelibos/sgx_sign.py line 291 at r1 (raw file):

Previously, dimakuv (Dmitrii Kuvaiskii) wrote…

Doesn't it fit into 100 chars per line? Also, no need for ()

Yes, it does. I have fixed it.


python/graminelibos/sgx_sign.py line 291 at r1 (raw file):

Previously, dimakuv (Dmitrii Kuvaiskii) wrote…

Why do you compare last_populated_addr against enclave_heap_min? Shouldn't it be attr['edmm_heap_prealloc_size']?

I adopted this check from https://github.com/gramineproject/gramine/blob/master/python/graminelibos/sgx_sign.py#L294. But I feel we should at least throw a warning. So have modified the code to be as below. Does this make sense?

     if attr['edmm_enable']:
         free_preallocated = []
-        if (attr['edmm_heap_prealloc_size'] > 0 and
-                last_populated_addr > enclave_heap_min):
+        if attr['edmm_heap_prealloc_size'] > 0:
+
+            if last_populated_addr < attr['edmm_heap_prealloc_size']:
+                raise Exception("Not enough space for edmm heap pre-allocation!")
+
+            if last_populated_addr < enclave_heap_min:
+                raise Exception("No space for heap!! Please check your manifest!")
 
             flags = PAGEINFO_R | PAGEINFO_W | PAGEINFO_X | PAGEINFO_REG
             start_addr = last_populated_addr - attr['edmm_heap_prealloc_size']
             if start_addr < enclave_heap_min:
-                raise Exception(" sgx.edmm_heap_prealloc_size cannot be more than total heap size!")
+                raise Exception("sgx.edmm_heap_prealloc_size cannot be more than total heap size!")

python/graminelibos/sgx_sign.py line 292 at r1 (raw file):

Previously, dimakuv (Dmitrii Kuvaiskii) wrote…

Please remove empty line

Done.


python/graminelibos/sgx_sign.py line 293 at r1 (raw file):

Previously, dimakuv (Dmitrii Kuvaiskii) wrote…

Oops, this is a security problem! When we use sgx.edmm_heap_prealloc_size, the pre-allocated range necessarily has RWX permissions. We should at least mention it in the documentation... I have no ideas how to solve it (if at all possible).

I didn't think of it before, but it's interesting: with this hybrid allocation, we trade security for performance. We kinda "drag" the SGXv1 page-permissions problem into the top part of the heap here.

Yes true, we do bring in SGX1, page permission limitations.


python/graminelibos/sgx_sign.py line 296 at r1 (raw file):

Previously, dimakuv (Dmitrii Kuvaiskii) wrote…

I would re-rephase like: sgx.edmm_heap_prealloc_size is greater than total heap size!

Done.


python/graminelibos/sgx_sign.py line 306 at r1 (raw file):

Previously, dimakuv (Dmitrii Kuvaiskii) wrote…

I'd prefer a separate PR.

OK, will do.


python/graminelibos/sgx_sign.py line 468 at r1 (raw file):

Previously, dimakuv (Dmitrii Kuvaiskii) wrote…

This function is so small and simple -- I wouldn't use empty lines here

Done.


python/graminelibos/sgx_sign.py line 469 at r1 (raw file):

Previously, dimakuv (Dmitrii Kuvaiskii) wrote…

This should return True and False

Done.


python/graminelibos/sgx_sign.py line 489 at r1 (raw file):

Previously, dimakuv (Dmitrii Kuvaiskii) wrote…

should -> must

along -> together

Done.


python/graminelibos/sgx_sign.py line 494 at r1 (raw file):

Previously, dimakuv (Dmitrii Kuvaiskii) wrote…

I suggest to remove this whole IF. I don't think the Python code must have such checks, that's just too much hand-holding of manifest writers.

I have removed this and also helper function is_aligned


python/graminelibos/sgx_sign.py line 536 at r1 (raw file):

Previously, dimakuv (Dmitrii Kuvaiskii) wrote…

The comment looks redundant, please remove

Done.


python/graminelibos/sgx_sign.py line 539 at r1 (raw file):

Previously, dimakuv (Dmitrii Kuvaiskii) wrote…

in enclave memory areas

Done.

Copy link
Contributor

@kailun-qin kailun-qin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewable status: 7 of 12 files reviewed, 54 unresolved discussions, not enough approvals from maintainers (3 more required), not enough approvals from different teams (2 more required, approved so far: ), "fixup! " found in commit messages' one-liners (waiting on @dimakuv and @vijaydhanraj)


Documentation/manifest-syntax.rst line 842 at r2 (raw file):

This option is invalid (i.e. must be ``false``) when only ``sgx.edmm_enable`` is
specified, as there are no heap pages to pre-fault. But if used together with

But also when sgx.edmm_heap_prealloc_size is set to 0?

Code quote:

This option is invalid (i.e. must be ``false``) when only ``sgx.edmm_enable`` is
specified, as there are no heap pages to pre-fault. But if used together with

pal/src/host/linux-sgx/enclave_edmm.c line 43 at r2 (raw file):

                |                      |
                +----------------------+ --> edmm_heap_prealloc_start
                |                      |     (heap_max + edmm_heap_prealloc_size)

Why not -?

Code quote:

+

pal/src/host/linux-sgx/enclave_edmm.c line 87 at r2 (raw file):

            /* Request is partially in pre-allocated range */
            memset((void*)(addr + count * PAGE_SIZE), 0, preallocated_count * PAGE_SIZE);
        }

Can we simply do memset((void*)(addr + count * PAGE_SIZE), 0, preallocated_count * PAGE_SIZE);?

Code quote:

        if (preallocated_count != 0) {
            /* Entire request is in pre-allocated range */
            if (count == 0) {
                memset((void*)addr, 0, preallocated_count * PAGE_SIZE);
                return 0;
            }

            /* Request is partially in pre-allocated range */
            memset((void*)(addr + count * PAGE_SIZE), 0, preallocated_count * PAGE_SIZE);
        }

pal/src/host/linux-sgx/host_main.c line 499 at r2 (raw file):

            } else {
                if (enclave->edmm_heap_prealloc_size > areas[i].size) {
                    log_error("edmm_heap_prealloc_size should be less than total heap size 0x%lx",

-> must; or should we actually align with the "edmm_heap_prealloc_size is greater than total heap size!" pattern in all similar places, as suggested by @dimakuv in python/graminelibos/sgx_sign.py?

Code quote:

should

python/graminelibos/sgx_sign.py line 293 at r1 (raw file):

We should at least mention it in the documentation...

+1

Copy link

@dimakuv dimakuv left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed 5 of 5 files at r2, all commit messages.
Reviewable status: all files reviewed, 18 unresolved discussions, not enough approvals from maintainers (3 more required), not enough approvals from different teams (2 more required, approved so far: ), "fixup! " found in commit messages' one-liners (waiting on @kailun-qin and @vijaydhanraj)


Documentation/manifest-syntax.rst line 486 at r2 (raw file):

   Support for EDMM first appeared in Linux 6.0.

EDMM heap pre-allocate size

pre-allocate -> pre-allocated


Documentation/manifest-syntax.rst line 497 at r2 (raw file):

to pre-allocate by setting this option. For example, when size is set to "64M"
Gramine will pre-allocate 64M of heap pages to the enclave (similar to SGXv1)
rather than allocating dynamically them. Higher values in this option may

Better wording:

... For example, when size is set to "64M",
Gramine will pre-allocate 64M of enclave memory (with read-write-execute
permissions!). Higher values in this option may ...

pal/src/host/linux-sgx/enclave_edmm.c line 84 at r1 (raw file):

Previously, vijaydhanraj (Vijay Dhanraj) wrote…

OK, done.

Why do you move the first comment out of the IF? I find it very counter-intuitive to read...


pal/src/host/linux-sgx/enclave_edmm.c line 35 at r2 (raw file):

/* Updates page count such that the request is fully below the pre-allocated
 * heap. If `count` is updated to 0, then the entire request overlaps with
 * pre-allocated heap.

This doesn't look 100-chars-per-line?


pal/src/host/linux-sgx/enclave_edmm.c line 43 at r2 (raw file):

Previously, kailun-qin (Kailun Qin) wrote…

Why not -?

Yes, should be -. It was my mistake in the other comment.


pal/src/host/linux-sgx/enclave_edmm.c line 87 at r2 (raw file):

Previously, kailun-qin (Kailun Qin) wrote…

Can we simply do memset((void*)(addr + count * PAGE_SIZE), 0, preallocated_count * PAGE_SIZE);?

@kailun-qin We need to return 0 in the first case, and we need to continue with SGX2 flows in the second case. That's why this distinction. I agree that memset() could be done only once, but the IFs are still required.


pal/src/host/linux-sgx/host_main.c line 719 at r1 (raw file):

Previously, vijaydhanraj (Vijay Dhanraj) wrote…

Added the checks in the untrusted PAL because, it here that we EADD the pages to enclave (as part of initialize_enclave()). Any incorrect values may result in EADD failing and it may not be clear why it failed.

Ah, I see your point.


pal/src/host/linux-sgx/host_main.c line 499 at r2 (raw file):

Previously, kailun-qin (Kailun Qin) wrote…

-> must; or should we actually align with the "edmm_heap_prealloc_size is greater than total heap size!" pattern in all similar places, as suggested by @dimakuv in python/graminelibos/sgx_sign.py?

Agree with @kailun-qin, let's just reuse the same message everywhere


python/graminelibos/sgx_sign.py line 285 at r1 (raw file):

Previously, vijaydhanraj (Vijay Dhanraj) wrote…

you mean to add then before add? Something like below?

    # Enclaves with EDMM do not add "free" memory at startup, but if heap is pre-allocated
    # using `sgx.edmm_heap_prealloc_size` then add the "free" pre-allocated pages.

Yes, sorry for confusion.


python/graminelibos/sgx_sign.py line 284 at r2 (raw file):

    #
    # Assumption here is that we have a single heap region (called "free") that is beneath all
    # other statically allocated memory areas(manifest, ssa, tls. tcs, stack, sig_stack, pal).

tls. -> tls,


python/graminelibos/sgx_sign.py line 290 at r2 (raw file):

            if last_populated_addr < attr['edmm_heap_prealloc_size']:
                raise Exception("Not enough space for edmm heap pre-allocation!")

We need to give some guidance to users what to do. Maybe add:

Increase 'sgx.enclave_size' or decrease 'sgx.edmm_heap_prealloc_size' in the manifest.

python/graminelibos/sgx_sign.py line 293 at r2 (raw file):

            if last_populated_addr < enclave_heap_min:
                raise Exception("No space for heap!! Please check your manifest!")
No space left for the heap! Increase 'sgx.enclave_size' in the manifest.

Copy link
Contributor

@kailun-qin kailun-qin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewable status: all files reviewed, 18 unresolved discussions, not enough approvals from maintainers (3 more required), not enough approvals from different teams (2 more required, approved so far: ), "fixup! " found in commit messages' one-liners (waiting on @dimakuv and @vijaydhanraj)


pal/src/host/linux-sgx/enclave_edmm.c line 87 at r2 (raw file):

We need to return 0 in the first case, and we need to continue with SGX2 flows in the second case. That's why this distinction.> the IFs are still required

Yes, I understand - sorry that I didn't write down the complete version. I was actually thinking about sth. like below:

memset((void*)(addr + count * PAGE_SIZE), 0, preallocated_count * PAGE_SIZE);
if (count == 0)
    return 0;

the IFs are still required

which memset() in any case but directly returns afterwards only if the entire request is in the pre-allocated range

Copy link

@dimakuv dimakuv left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewable status: all files reviewed, 18 unresolved discussions, not enough approvals from maintainers (3 more required), not enough approvals from different teams (2 more required, approved so far: ), "fixup! " found in commit messages' one-liners (waiting on @kailun-qin and @vijaydhanraj)


pal/src/host/linux-sgx/enclave_edmm.c line 87 at r2 (raw file):

Previously, kailun-qin (Kailun Qin) wrote…

We need to return 0 in the first case, and we need to continue with SGX2 flows in the second case. That's why this distinction.> the IFs are still required

Yes, I understand - sorry that I didn't write down the complete version. I was actually thinking about sth. like below:

memset((void*)(addr + count * PAGE_SIZE), 0, preallocated_count * PAGE_SIZE);
if (count == 0)
    return 0;

the IFs are still required

which memset() in any case but directly returns afterwards only if the entire request is in the pre-allocated range

Yeah, I'd be fine with this change

Copy link
Contributor Author

@vijaydhanraj vijaydhanraj left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewable status: 8 of 12 files reviewed, 18 unresolved discussions, not enough approvals from maintainers (3 more required), not enough approvals from different teams (2 more required, approved so far: ), "fixup! " found in commit messages' one-liners (waiting on @dimakuv and @kailun-qin)


Documentation/manifest-syntax.rst line 486 at r2 (raw file):

Previously, dimakuv (Dmitrii Kuvaiskii) wrote…

pre-allocate -> pre-allocated

Done.


Documentation/manifest-syntax.rst line 497 at r2 (raw file):

Previously, dimakuv (Dmitrii Kuvaiskii) wrote…

Better wording:

... For example, when size is set to "64M",
Gramine will pre-allocate 64M of enclave memory (with read-write-execute
permissions!). Higher values in this option may ...

Done. I removed the ! as it sounds like an alarm and instead referenced the similarity to SGXv1.


Documentation/manifest-syntax.rst line 842 at r2 (raw file):

Previously, kailun-qin (Kailun Qin) wrote…

But also when sgx.edmm_heap_prealloc_size is set to 0?

I don't think we need to explicitly callout as sgx.edmm_heap_prealloc_size = 0 means the feature is off and our text reads "when only sgx.edmm_enable is ....". So, looks fine to me but open to adding additional text as well if it isn't clear.


pal/src/host/linux-sgx/enclave_edmm.c line 84 at r1 (raw file):

Previously, dimakuv (Dmitrii Kuvaiskii) wrote…

Why do you move the first comment out of the IF? I find it very counter-intuitive to read...

Moved it inside the if statement.


pal/src/host/linux-sgx/enclave_edmm.c line 35 at r2 (raw file):

Previously, dimakuv (Dmitrii Kuvaiskii) wrote…

This doesn't look 100-chars-per-line?

yes, re-wrapped it.


pal/src/host/linux-sgx/enclave_edmm.c line 43 at r2 (raw file):

Previously, dimakuv (Dmitrii Kuvaiskii) wrote…

Yes, should be -. It was my mistake in the other comment.

Not sure but have replaced + with -. Is this what we want?


pal/src/host/linux-sgx/enclave_edmm.c line 87 at r2 (raw file):

Previously, dimakuv (Dmitrii Kuvaiskii) wrote…

Yeah, I'd be fine with this change

Done.


pal/src/host/linux-sgx/host_main.c line 499 at r2 (raw file):

Previously, dimakuv (Dmitrii Kuvaiskii) wrote…

Agree with @kailun-qin, let's just reuse the same message everywhere

Since heap size can vary, it will be better if we can print the actual heap size and tell the user to set a lesser value. So, the current print message may be better. I have changed even in sgx_sign.py file for uniformity. Let me know if we want to revert it.


python/graminelibos/sgx_sign.py line 284 at r2 (raw file):

Previously, dimakuv (Dmitrii Kuvaiskii) wrote…

tls. -> tls,

Done.


python/graminelibos/sgx_sign.py line 290 at r2 (raw file):

Previously, dimakuv (Dmitrii Kuvaiskii) wrote…

We need to give some guidance to users what to do. Maybe add:

Increase 'sgx.enclave_size' or decrease 'sgx.edmm_heap_prealloc_size' in the manifest.

Done.


python/graminelibos/sgx_sign.py line 293 at r2 (raw file):

Previously, dimakuv (Dmitrii Kuvaiskii) wrote…
No space left for the heap! Increase 'sgx.enclave_size' in the manifest.

Done.

Copy link
Contributor Author

@vijaydhanraj vijaydhanraj left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewable status: 8 of 12 files reviewed, 18 unresolved discussions, not enough approvals from maintainers (3 more required), not enough approvals from different teams (2 more required, approved so far: ), "fixup! " found in commit messages' one-liners (waiting on @dimakuv and @kailun-qin)


pal/src/host/linux-sgx/enclave_edmm.c line 43 at r2 (raw file):

Previously, vijaydhanraj (Vijay Dhanraj) wrote…

Not sure but have replaced + with -. Is this what we want?

Misunderstood the comment earlier and fixed the typo.

Copy link

@dimakuv dimakuv left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed 4 of 4 files at r3, all commit messages.
Reviewable status: all files reviewed, 13 unresolved discussions, not enough approvals from maintainers (2 more required), not enough approvals from different teams (2 more required, approved so far: ), "fixup! " found in commit messages' one-liners (waiting on @kailun-qin and @vijaydhanraj)


Documentation/manifest-syntax.rst line 497 at r2 (raw file):

Previously, vijaydhanraj (Vijay Dhanraj) wrote…

Done. I removed the ! as it sounds like an alarm and instead referenced the similarity to SGXv1.

Yes, thanks, your variant reads much better.


Documentation/manifest-syntax.rst line 842 at r2 (raw file):

Previously, vijaydhanraj (Vijay Dhanraj) wrote…

I don't think we need to explicitly callout as sgx.edmm_heap_prealloc_size = 0 means the feature is off and our text reads "when only sgx.edmm_enable is ....". So, looks fine to me but open to adding additional text as well if it isn't clear.

I agree with Vijay, Kailun's proposed addition sounds not important (as it should be obvious to readers).


pal/src/host/linux-sgx/host_main.c line 499 at r2 (raw file):

Previously, vijaydhanraj (Vijay Dhanraj) wrote…

Since heap size can vary, it will be better if we can print the actual heap size and tell the user to set a lesser value. So, the current print message may be better. I have changed even in sgx_sign.py file for uniformity. Let me know if we want to revert it.

Looks good to me.


pal/src/host/linux-sgx/host_main.c line 499 at r3 (raw file):

            } else {
                if (enclave->edmm_heap_prealloc_size > areas[i].size) {
                    log_error("'sgx.edmm_heap_prealloc_size' must be less than total heap size 0x%lx",

Please re-wrap to 100 chars per line


python/graminelibos/sgx_sign.py line 295 at r3 (raw file):

            if last_populated_addr < enclave_heap_min:
                raise Exception("No space for heap!! Increase 'sgx.enclave_size' in the manifest.")

Please !! to ! (leave only one exclamatory mark)

Copy link
Contributor Author

@vijaydhanraj vijaydhanraj left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewable status: 10 of 12 files reviewed, 14 unresolved discussions, not enough approvals from maintainers (2 more required), not enough approvals from different teams (2 more required, approved so far: ), "fixup! " found in commit messages' one-liners (waiting on @dimakuv and @kailun-qin)

a discussion (no related file):
@dimakuv @kailun-qin if you are done with initial round of reviews for this PR, then can you please trigger EDMM CI pipeline with sgx.edmm_heap_prealloc_size say set to 64M?

If things look fine, we can start with performance evaluation.



pal/src/host/linux-sgx/host_main.c line 499 at r3 (raw file):

Previously, dimakuv (Dmitrii Kuvaiskii) wrote…

Please re-wrap to 100 chars per line

Done.


python/graminelibos/sgx_sign.py line 295 at r3 (raw file):

Previously, dimakuv (Dmitrii Kuvaiskii) wrote…

Please !! to ! (leave only one exclamatory mark)

Done.

Copy link
Contributor

@kailun-qin kailun-qin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewable status: 10 of 12 files reviewed, 13 unresolved discussions, not enough approvals from maintainers (2 more required), not enough approvals from different teams (2 more required, approved so far: ), "fixup! " found in commit messages' one-liners (waiting on @dimakuv and @vijaydhanraj)

a discussion (no related file):

then can you please trigger EDMM CI pipeline

Sure

with sgx.edmm_heap_prealloc_size say set to 64M?

But I don't think we can trigger CI pipelines w/ a specific manifest option.

How to test this PR?
Regular EDMM CI pipeline with sgx.edmm_heap_prealloc_size.

If we'd like to cover/test this in EDMM CI, we may need some updates then.



-- commits line 2 at r1:

Previously, vijaydhanraj (Vijay Dhanraj) wrote…

How about Introduce EDMM pre-allocated heap optimization?

Maybe "Introduce EDMM heap pre-allocation"?


Documentation/manifest-syntax.rst line 842 at r2 (raw file):

Previously, dimakuv (Dmitrii Kuvaiskii) wrote…

I agree with Vijay, Kailun's proposed addition sounds not important (as it should be obvious to readers).

Sure, I don't insist on this. Let me resolve then.


pal/src/host/linux-sgx/enclave_edmm.c line 43 at r2 (raw file):

Previously, vijaydhanraj (Vijay Dhanraj) wrote…

Misunderstood the comment earlier and fixed the typo.

Yep, I meant the - in the calculation of edmm_heap_prealloc_start. Sorry about the misunderstanding.


pal/src/host/linux-sgx/enclave_edmm.c line 87 at r2 (raw file):

Previously, vijaydhanraj (Vijay Dhanraj) wrote…

Done.

I guess the IF for preallocated_count != 0 is even not needed. Anyway, I don't insist :).


pal/src/host/linux-sgx/host_main.c line 499 at r2 (raw file):

Previously, dimakuv (Dmitrii Kuvaiskii) wrote…

Looks good to me.

Looks good to me, resolving.


python/graminelibos/sgx_sign.py line 466 at r4 (raw file):

def check_memory_area_holes(attr, areas, enclave_base):

What about check_non_contiguous_memory_areas()?

Code quote:

check_memory_area_holes

python/graminelibos/sgx_sign.py line 536 at r4 (raw file):

    memory_area_holes = check_memory_area_holes(attr, memory_areas, enclave_base)
    if memory_area_holes:

-->

if check_non_contiguous_memory_areas(...):
    raise Exception('Cannot have holes in enclave memory areas!')

Code quote:

    memory_area_holes = check_memory_area_holes(attr, memory_areas, enclave_base)
    if memory_area_holes:

python/graminelibos/sgx_sign.py line 537 at r4 (raw file):

    memory_area_holes = check_memory_area_holes(attr, memory_areas, enclave_base)
    if memory_area_holes:
        raise Exception('Cannot have holes in enclave memory areas!')

between?

Code quote:

in

Copy link
Contributor Author

@vijaydhanraj vijaydhanraj left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewable status: 10 of 12 files reviewed, 13 unresolved discussions, not enough approvals from maintainers (2 more required), not enough approvals from different teams (2 more required, approved so far: ), "fixup! " found in commit messages' one-liners (waiting on @dimakuv and @kailun-qin)

a discussion (no related file):

Previously, kailun-qin (Kailun Qin) wrote…

then can you please trigger EDMM CI pipeline

Sure

with sgx.edmm_heap_prealloc_size say set to 64M?

But I don't think we can trigger CI pipelines w/ a specific manifest option.

How to test this PR?
Regular EDMM CI pipeline with sgx.edmm_heap_prealloc_size.

If we'd like to cover/test this in EDMM CI, we may need some updates then.

I do have a patch where I have set sgx.edmm_heap_prealloc_size = 64M for all the PAL and LibOS regression test manifest templates. I can also set this manifest option in https://github.com/gramineproject/gramine/blob/master/libos/test/ltp/manifest.template. Would this help?



-- commits line 2 at r1:

Previously, kailun-qin (Kailun Qin) wrote…

Maybe "Introduce EDMM heap pre-allocation"?

Yes, it looks good to me.


pal/src/host/linux-sgx/enclave_edmm.c line 87 at r2 (raw file):

Previously, kailun-qin (Kailun Qin) wrote…

I guess the IF for preallocated_count != 0 is even not needed. Anyway, I don't insist :).

The preallocated_count != 0 check ensures that we do memset only on statically allocated memory (SGXv1). If we remove this check, we will end up doing memset even for dynamically allocated pages which might lead to a seg-fault.


python/graminelibos/sgx_sign.py line 466 at r4 (raw file):

Previously, kailun-qin (Kailun Qin) wrote…

What about check_non_contiguous_memory_areas()?

If this is preferred, I can update the function.

Copy link

@dimakuv dimakuv left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed 2 of 2 files at r4, all commit messages.
Reviewable status: all files reviewed, 11 unresolved discussions, not enough approvals from maintainers (2 more required), not enough approvals from different teams (2 more required, approved so far: ), "fixup! " found in commit messages' one-liners (waiting on @kailun-qin and @vijaydhanraj)

a discussion (no related file):

But I don't think we can trigger CI pipelines w/ a specific manifest option.

Yes, we can't do that.

LTP is not tested in SGX mode (only in direct mode). Thus it won't help.

You can add this option to LibOS regression's manifest.template common file. It should be protected with env.get('EDMM'), similarly to this line:

sgx.edmm_enable = {{ 'true' if env.get('EDMM', '0') == '1' else 'false' }}



python/graminelibos/sgx_sign.py line 466 at r4 (raw file):

Previously, vijaydhanraj (Vijay Dhanraj) wrote…

If this is preferred, I can update the function.

I don't care about the name, I think the current one is also fine.


python/graminelibos/sgx_sign.py line 536 at r4 (raw file):

Previously, kailun-qin (Kailun Qin) wrote…

-->

if check_non_contiguous_memory_areas(...):
    raise Exception('Cannot have holes in enclave memory areas!')

Yes, let's simplify as Kailun suggested (remove the temporary var memory_area_holes)

But now the function name will be ambigious. So I suggest to rename to has_memory_area_holes()


python/graminelibos/sgx_sign.py line 537 at r4 (raw file):

Previously, kailun-qin (Kailun Qin) wrote…

between?

+1 to between

Copy link
Contributor Author

@vijaydhanraj vijaydhanraj left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewable status: all files reviewed, 11 unresolved discussions, not enough approvals from maintainers (2 more required), not enough approvals from different teams (2 more required, approved so far: ), "fixup! " found in commit messages' one-liners (waiting on @dimakuv and @kailun-qin)

a discussion (no related file):

Previously, dimakuv (Dmitrii Kuvaiskii) wrote…

But I don't think we can trigger CI pipelines w/ a specific manifest option.

Yes, we can't do that.

LTP is not tested in SGX mode (only in direct mode). Thus it won't help.

You can add this option to LibOS regression's manifest.template common file. It should be protected with env.get('EDMM'), similarly to this line:

sgx.edmm_enable = {{ 'true' if env.get('EDMM', '0') == '1' else 'false' }}

Something like this sgx.edmm_heap_prealloc_size = {{ "\"64M\"" if env.get('EDMM', '0') == '1' else "\"0\"" }}?
And why only manifest.template? This should be added for other *.template files in PAL and LibOS as well, right? If this is fine, I can create a temporary commit with this manifest option enabled.



python/graminelibos/sgx_sign.py line 466 at r4 (raw file):

Previously, dimakuv (Dmitrii Kuvaiskii) wrote…

I don't care about the name, I think the current one is also fine.

Changed to has_memory_area_holes


python/graminelibos/sgx_sign.py line 536 at r4 (raw file):

Previously, dimakuv (Dmitrii Kuvaiskii) wrote…

Yes, let's simplify as Kailun suggested (remove the temporary var memory_area_holes)

But now the function name will be ambigious. So I suggest to rename to has_memory_area_holes()

Done.


python/graminelibos/sgx_sign.py line 537 at r4 (raw file):

Previously, dimakuv (Dmitrii Kuvaiskii) wrote…

+1 to between

Done.

This commit enables `sgx.edmm_heap_prealloc_size` manifest option
on CI platforms that support EDMM. Currently this option is set only
for a subset of LibOS regression tests for verification.

Signed-off-by: Vijay Dhanraj <vijay.dhanraj@intel.com>
Copy link
Contributor Author

@vijaydhanraj vijaydhanraj left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewable status: 11 of 13 files reviewed, 11 unresolved discussions, not enough approvals from maintainers (2 more required), not enough approvals from different teams (2 more required, approved so far: ), "fixup! " found in commit messages' one-liners (waiting on @dimakuv and @kailun-qin)

a discussion (no related file):

Previously, vijaydhanraj (Vijay Dhanraj) wrote…

Something like this sgx.edmm_heap_prealloc_size = {{ "\"64M\"" if env.get('EDMM', '0') == '1' else "\"0\"" }}?
And why only manifest.template? This should be added for other *.template files in PAL and LibOS as well, right? If this is fine, I can create a temporary commit with this manifest option enabled.

Created a new commit to enable sgx.edmm_heap_prealloc_size in LibOS regression's manifest.template file.


Copy link

@dimakuv dimakuv left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed 2 of 2 files at r5, all commit messages.
Reviewable status: all files reviewed, 11 unresolved discussions, not enough approvals from maintainers (2 more required), not enough approvals from different teams (2 more required, approved so far: ), "fixup! " found in commit messages' one-liners (waiting on @kailun-qin and @vijaydhanraj)


libos/test/regression/manifest.template line 27 at r5 (raw file):

sgx.debug = true
sgx.edmm_enable = {{ 'true' if env.get('EDMM', '0') == '1' else 'false' }}
sgx.edmm_heap_prealloc_size = {{ "\"64M\"" if env.get('EDMM', '0') == '1' else "\"0\"" }}

I guess you could move the " outside of the Jinja syntax, and then you wouldn't require this ugly escaping:

sgx.edmm_heap_prealloc_size = "{{ '64M' if env.get('EDMM', '0') == '1' else '0' }}"

Please check if it correctly renders, and if yes, replace as suggested.

Copy link
Contributor Author

@vijaydhanraj vijaydhanraj left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewable status: all files reviewed, 11 unresolved discussions, not enough approvals from maintainers (2 more required), not enough approvals from different teams (2 more required, approved so far: ), "fixup! " found in commit messages' one-liners (waiting on @dimakuv and @kailun-qin)


libos/test/regression/manifest.template line 27 at r5 (raw file):

Previously, dimakuv (Dmitrii Kuvaiskii) wrote…

I guess you could move the " outside of the Jinja syntax, and then you wouldn't require this ugly escaping:

sgx.edmm_heap_prealloc_size = "{{ '64M' if env.get('EDMM', '0') == '1' else '0' }}"

Please check if it correctly renders, and if yes, replace as suggested.

Looks much better, thanks!

Copy link

@dimakuv dimakuv left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed 1 of 1 files at r6, all commit messages.
Reviewable status: all files reviewed, 10 unresolved discussions, not enough approvals from maintainers (2 more required), not enough approvals from different teams (2 more required, approved so far: ), "fixup! " found in commit messages' one-liners (waiting on @kailun-qin)

@dimakuv
Copy link

dimakuv commented Apr 13, 2023

Jenkins, test this please

Copy link
Contributor

@jinengandhi-intel jinengandhi-intel left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewable status: all files reviewed, 11 unresolved discussions, not enough approvals from maintainers (2 more required), not enough approvals from different teams (2 more required, approved so far: ), "fixup! " found in commit messages' one-liners (waiting on @dimakuv, @kailun-qin, and @vijaydhanraj)

a discussion (no related file):
@vijaydhanraj Do we have plans to update the manifest template files for CI-Examples? As in add the following to all manifest template files: sgx.edmm_heap_prealloc_size = "{{ '64M' if env.get('EDMM', '0') == '1' else '0' }}"


Copy link

@dimakuv dimakuv left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewable status: all files reviewed, 11 unresolved discussions, not enough approvals from maintainers (2 more required), not enough approvals from different teams (2 more required, approved so far: ), "fixup! " found in commit messages' one-liners (waiting on @kailun-qin and @vijaydhanraj)

a discussion (no related file):

Previously, jinengandhi-intel wrote…

@vijaydhanraj Do we have plans to update the manifest template files for CI-Examples? As in add the following to all manifest template files: sgx.edmm_heap_prealloc_size = "{{ '64M' if env.get('EDMM', '0') == '1' else '0' }}"

@jinengandhi-intel I think it's too early for this, because we'll need to first figure out the best "preallocated size" value for each example. E.g., something like Helloworld example doesn't need this at all, but something like PyTorch or TensorFlow would probably need 256M or even more.

I would say adding this new option to our examples/workloads is a future task, after we find the best values.


Copy link
Contributor

@jinengandhi-intel jinengandhi-intel left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewable status: all files reviewed, 11 unresolved discussions, not enough approvals from maintainers (2 more required), not enough approvals from different teams (2 more required, approved so far: ), "fixup! " found in commit messages' one-liners (waiting on @dimakuv, @kailun-qin, and @vijaydhanraj)

a discussion (no related file):

Previously, dimakuv (Dmitrii Kuvaiskii) wrote…

@jinengandhi-intel I think it's too early for this, because we'll need to first figure out the best "preallocated size" value for each example. E.g., something like Helloworld example doesn't need this at all, but something like PyTorch or TensorFlow would probably need 256M or even more.

I would say adding this new option to our examples/workloads is a future task, after we find the best values.

@vijaydhanraj would you be running these experiments or you need help from the team here? From what I understand we would need to check functionality as well as evaluate performance for all workloads that we currently have baselines for. Last release when we had enabled EDMM, perf with and without EDMM was almost the same for most workloads. With this PR we expect to see some perf improvements, please correct if I am wrong.


Copy link
Contributor Author

@vijaydhanraj vijaydhanraj left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewable status: all files reviewed, 11 unresolved discussions, not enough approvals from maintainers (2 more required), not enough approvals from different teams (2 more required, approved so far: ), "fixup! " found in commit messages' one-liners (waiting on @dimakuv, @jinengandhi-intel, and @kailun-qin)

a discussion (no related file):
@jinengandhi-intel I will need help with running these experiments from the team and yes, we need to evaluate both functionality and performance.

Last release when we had enabled EDMM, perf with and without EDMM was almost the same for most workloads. With this PR we expect to see some perf improvements, please correct if I am wrong.

We need to investigate 2 aspects of performance, 1) load time performance 2) runtime performance. With existing naive support, we would see improvement in load time, but the runtime performance may be impacted. This may be the reason why few workloads failed with timeout errors.

With this PR, we are trying to balance between load time and runtime. So, with higher sgx.edmm_heap_prealloc_size the load time will be impacted but the runtime will improve and vice versa. The goal of the performance evaluation would be to find a sweet spot between load time and runtime.


Copy link
Contributor

@jinengandhi-intel jinengandhi-intel left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewable status: all files reviewed, 11 unresolved discussions, not enough approvals from maintainers (2 more required), not enough approvals from different teams (2 more required, approved so far: ), "fixup! " found in commit messages' one-liners (waiting on @dimakuv, @kailun-qin, and @vijaydhanraj)

a discussion (no related file):

Previously, vijaydhanraj (Vijay Dhanraj) wrote…

@jinengandhi-intel I will need help with running these experiments from the team and yes, we need to evaluate both functionality and performance.

Last release when we had enabled EDMM, perf with and without EDMM was almost the same for most workloads. With this PR we expect to see some perf improvements, please correct if I am wrong.

We need to investigate 2 aspects of performance, 1) load time performance 2) runtime performance. With existing naive support, we would see improvement in load time, but the runtime performance may be impacted. This may be the reason why few workloads failed with timeout errors.

With this PR, we are trying to balance between load time and runtime. So, with higher sgx.edmm_heap_prealloc_size the load time will be impacted but the runtime will improve and vice versa. The goal of the performance evaluation would be to find a sweet spot between load time and runtime.

@vijaydhanraj To begin with I did some functional validation with the PR which included running LTP tests with Gramine SGX and EDMM enabled and all workloads from CI-Examples as well as in the examples repo. For all of the above tests the manifest file was configured with the default heap size of 64M and I didn't see any functional issues. Validation was done on Ubuntu22.04 as well as RHEL8. So from a functionality standpoint 64M size worked for me.

In parallel Vasanth from my team has started the perf runs but this will take time as there are many workloads and each of them needs to be run with different heap size to find the best configuration. Will update once we have some results to share.


Copy link

@dimakuv dimakuv left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewable status: all files reviewed, 12 unresolved discussions, not enough approvals from maintainers (2 more required), not enough approvals from different teams (2 more required, approved so far: ), "fixup! " found in commit messages' one-liners (waiting on @kailun-qin and @vijaydhanraj)

a discussion (no related file):
I would like to block this PR until we resolve a high-level discussion: given #1513, do we want this hacky hybrid-allocation approach? This approach has two issues:

  1. Security -- preallocated pages must have RWX permissions.
  2. Cleanliness -- this approach relies on the fact that initially used memory is allocated from the top of the enclave. This may bite us when we modify this assumption.

With #1513, I think we could re-use the lazy-allocation flag from there, to introduce a similar optimization to this hybrid-alloc, but using the same generic mechanism (the bitvector of committed pages) as in #1513.

I am very much in favor of re-using #1513 rather than this PR.


Copy link
Contributor

@efu39 efu39 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems that the pre-allocated heap memory is only guaranteed to be used when ASLR is disabled in this approach? By default ASLR is enabled and the top address is changed and not the same as heap_max.

Reviewable status: all files reviewed, 12 unresolved discussions, not enough approvals from maintainers (2 more required), not enough approvals from different teams (2 more required, approved so far: ), "fixup! " found in commit messages' one-liners (waiting on @dimakuv, @kailun-qin, and @vijaydhanraj)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[LibOS,PAL/Linux-SGX] EDMM: Introduce Hybrid Allocation
5 participants