From: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
To: Thomas Gleixner <tglx@linutronix.de>
Cc: <x86@kernel.org>, <platform-driver-x86@vger.kernel.org>,
<dave.hansen@intel.com>, <sean.j.christopherson@intel.com>,
<nhorman@redhat.com>, <npmccallum@redhat.com>,
<linux-sgx@vger.kernel.org>, Ingo Molnar <mingo@redhat.com>,
"H. Peter Anvin" <hpa@zytor.com>,
"open list:X86 ARCHITECTURE (32-BIT AND 64-BIT)"
<linux-kernel@vger.kernel.org>
Subject: Re: [PATCH v12 09/13] x86/sgx: EPC page allocation routines
Date: Wed, 4 Jul 2018 21:24:19 +0300 [thread overview]
Message-ID: <20180704182419.GO6724@linux.intel.com> (raw)
In-Reply-To: <alpine.DEB.2.21.1807032216390.1816@nanos.tec.linutronix.de>
On Tue, Jul 03, 2018 at 10:41:14PM +0200, Thomas Gleixner wrote:
> On Tue, 3 Jul 2018, Jarkko Sakkinen wrote:
> >
> > +#define SGX_NR_TO_SCAN 16
> > +#define SGX_NR_LOW_PAGES 32
> > +#define SGX_NR_HIGH_PAGES 64
> > +
> > bool sgx_enabled __ro_after_init;
> > EXPORT_SYMBOL(sgx_enabled);
> > bool sgx_lc_enabled __ro_after_init;
> > EXPORT_SYMBOL(sgx_lc_enabled);
> > +LIST_HEAD(sgx_active_page_list);
> > +EXPORT_SYMBOL(sgx_active_page_list);
> > +DEFINE_SPINLOCK(sgx_active_page_list_lock);
> > +EXPORT_SYMBOL(sgx_active_page_list_lock);
>
> Why is all of this exported. If done right then no call site has to fiddle
> with the list and the lock at all.
We can fix this in a way that these exports are not needed. Thanks
for pointing this out.
> > static atomic_t sgx_nr_free_pages = ATOMIC_INIT(0);
> > static struct sgx_epc_bank sgx_epc_banks[SGX_MAX_EPC_BANKS];
> > static int sgx_nr_epc_banks;
> > +static struct task_struct *ksgxswapd_tsk;
> > +static DECLARE_WAIT_QUEUE_HEAD(ksgxswapd_waitq);
> > +
> > +static void sgx_swap_cluster(void)
> > +{
> > + struct sgx_epc_page *cluster[SGX_NR_TO_SCAN + 1];
> > + struct sgx_epc_page *epc_page;
> > + int i;
> > + int j;
>
> int i, j;
I've always preferred single declaration per line even for index
variables but not something that I'm going to argue about too
much.
> > + memset(cluster, 0, sizeof(cluster));
> > +
> > + for (i = 0, j = 0; i < SGX_NR_TO_SCAN; i++) {
> > + spin_lock(&sgx_active_page_list_lock);
> > + if (list_empty(&sgx_active_page_list)) {
> > + spin_unlock(&sgx_active_page_list_lock);
> > + break;
> > + }
> > + epc_page = list_first_entry(&sgx_active_page_list,
> > + struct sgx_epc_page, list);
> > + if (!epc_page->impl->ops->get(epc_page)) {
> > + list_move_tail(&epc_page->list, &sgx_active_page_list);
> > + spin_unlock(&sgx_active_page_list_lock);
> > + continue;
> > + }
> > + list_del(&epc_page->list);
> > + spin_unlock(&sgx_active_page_list_lock);
> > +
> > + if (epc_page->impl->ops->reclaim(epc_page)) {
> > + cluster[j++] = epc_page;
> > + } else {
> > + spin_lock(&sgx_active_page_list_lock);
> > + list_add_tail(&epc_page->list, &sgx_active_page_list);
> > + spin_unlock(&sgx_active_page_list_lock);
> > + epc_page->impl->ops->put(epc_page);
> > + }
> > + }
> > +
> > + for (i = 0; cluster[i]; i++) {
> > + epc_page = cluster[i];
> > + epc_page->impl->ops->block(epc_page);
> > + }
> > +
> > + for (i = 0; cluster[i]; i++) {
> > + epc_page = cluster[i];
> > + epc_page->impl->ops->write(epc_page);
> > + epc_page->impl->ops->put(epc_page);
> > + sgx_free_page(epc_page);
> > + }
>
> Thanks a lot for commenting this piece of art thoughtfully. It's entirely
> clear how all of this works now.
Got your point.
> > +}
> > +
> > +static int ksgxswapd(void *p)
> > +{
> > + set_freezable();
> > +
> > + while (!kthread_should_stop()) {
> > + if (try_to_freeze())
> > + continue;
> > +
> > + wait_event_freezable(ksgxswapd_waitq, kthread_should_stop() ||
> > + atomic_read(&sgx_nr_free_pages) <
> > + SGX_NR_HIGH_PAGES);
> > +
> > + if (atomic_read(&sgx_nr_free_pages) < SGX_NR_HIGH_PAGES)
> > + sgx_swap_cluster();
> > + }
> > +
> > + pr_info("%s: done\n", __func__);
>
> Really useful.
Forgotten cruft, will remove.
> > + return 0;
> > +}
> > +
> > +static struct sgx_epc_page *sgx_try_alloc_page(struct sgx_epc_page_impl *impl)
> > +{
> > + struct sgx_epc_bank *bank;
> > + struct sgx_epc_page *page = NULL;
> > + int i;
> > +
> > + for (i = 0; i < sgx_nr_epc_banks; i++) {
> > + bank = &sgx_epc_banks[i];
> > +
> > + down_write(&bank->lock);
> > +
> > + if (atomic_read(&bank->free_cnt))
>
> And these atomics are required becasue bank->lock protection is not
> sufficient or what am I missing here?
This is also response to your comment below. It would be better idea
to just use a spinlock I guess. Seeing your and Daves point.
> > + page = bank->pages[atomic_dec_return(&bank->free_cnt)];
> > +
> > + up_write(&bank->lock);
> > +
> > + if (page)
> > + break;
> > + }
> > +
> > + if (page) {
> > + atomic_dec(&sgx_nr_free_pages);
> > + page->impl = impl;
> > + }
> > +
> > + return page;
> > +}
> > +
> > +/**
> > + * sgx_alloc_page - allocate an EPC page
> > + * @flags: allocation flags
> > + * @impl: implementation for the struct sgx_epc_page
> > + *
> > + * Try to grab a page from the free EPC page list. If there is a free page
> > + * available, it is returned to the caller. If called with SGX_ALLOC_ATOMIC,
> > + * the function will return immediately if the list is empty. Otherwise, it
> > + * will swap pages up until there is a free page available. Upon returning the
> > + * low watermark is checked and ksgxswapd is waken up if we are below it.
> > + *
> > + * Return:
> > + * a &struct sgx_epc_page instace,
> > + * -ENOMEM if all pages are unreclaimable,
> > + * -EBUSY when called with SGX_ALLOC_ATOMIC and out of free pages
> > + */
> > +struct sgx_epc_page *sgx_alloc_page(struct sgx_epc_page_impl *impl,
> > + unsigned int flags)
> > +{
> > + struct sgx_epc_page *entry;
> > +
> > + for ( ; ; ) {
> > + entry = sgx_try_alloc_page(impl);
> > + if (entry)
> > + break;
> > +
> > + if (list_empty(&sgx_active_page_list))
> > + return ERR_PTR(-ENOMEM);
> > +
> > + if (flags & SGX_ALLOC_ATOMIC) {
> > + entry = ERR_PTR(-EBUSY);
> > + break;
> > + }
> > +
> > + if (signal_pending(current)) {
> > + entry = ERR_PTR(-ERESTARTSYS);
> > + break;
> > + }
> > +
> > + sgx_swap_cluster();
> > + schedule();
> > + }
> > +
> > + if (atomic_read(&sgx_nr_free_pages) < SGX_NR_LOW_PAGES)
> > + wake_up(&ksgxswapd_waitq);
>
> What's the logic of SGX_NR_LOW_PAGES vs. SGX_NR_HIGH_PAGES?
If the number of pages goes below SGX_NR_LOW_PAGES ksgxswapd swaps pages
up until SGX_NR_HIGH_PAGES is reached.
>
> > +
> > + return entry;
> > +}
> > +EXPORT_SYMBOL(sgx_alloc_page);
> > +
> > +/**
> > + * sgx_free_page - free an EPC page
> > + *
> > + * @page: any EPC page
> > + *
> > + * Remove an EPC page and insert it back to the list of free pages.
> > + *
> > + * Return: SGX error code
> > + */
> > +int sgx_free_page(struct sgx_epc_page *page)
> > +{
> > + struct sgx_epc_bank *bank = SGX_EPC_BANK(page);
> > + int ret;
> > +
> > + ret = sgx_eremove(page);
> > + if (ret) {
> > + pr_debug("EREMOVE returned %d\n", ret);
> > + return ret;
> > + }
> > +
> > + down_read(&bank->lock);
> > + bank->pages[atomic_inc_return(&bank->free_cnt) - 1] = page;
> > + atomic_inc(&sgx_nr_free_pages);
> > + up_read(&bank->lock);
>
> I have hard time to see the benefit of this reader/writer semaphore
> here. Both sides which fiddle with the bank pages are doing a simple
> de/increment of free_cnt and a store resp. load. So what justifies the
> overhead of a rwsem?
>
> > static __init int sgx_init_epc_bank(unsigned long addr, unsigned long size,
> > unsigned long index,
> > struct sgx_epc_bank *bank)
> > @@ -114,6 +318,11 @@ static __init void sgx_page_cache_teardown(void)
> > kfree(bank->pages);
> > kfree(bank->pages_data);
> > }
> > +
> > + if (ksgxswapd_tsk) {
> > + kthread_stop(ksgxswapd_tsk);
> > + ksgxswapd_tsk = NULL;
>
> This stops the thread _AFTER_ freeing all the bank memory. Is that actually
> correct?
Should not cause any actual regressions but is a flakky order anyway
so I will change it.
/Jarkko
WARNING: multiple messages have this Message-ID (diff)
From: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
To: Thomas Gleixner <tglx@linutronix.de>
Cc: x86@kernel.org, platform-driver-x86@vger.kernel.org,
dave.hansen@intel.com, sean.j.christopherson@intel.com,
nhorman@redhat.com, npmccallum@redhat.com,
linux-sgx@vger.kernel.org, Ingo Molnar <mingo@redhat.com>,
"H. Peter Anvin" <hpa@zytor.com>,
"open list:X86 ARCHITECTURE (32-BIT AND 64-BIT)"
<linux-kernel@vger.kernel.org>
Subject: Re: [PATCH v12 09/13] x86/sgx: EPC page allocation routines
Date: Wed, 4 Jul 2018 21:24:19 +0300 [thread overview]
Message-ID: <20180704182419.GO6724@linux.intel.com> (raw)
In-Reply-To: <alpine.DEB.2.21.1807032216390.1816@nanos.tec.linutronix.de>
On Tue, Jul 03, 2018 at 10:41:14PM +0200, Thomas Gleixner wrote:
> On Tue, 3 Jul 2018, Jarkko Sakkinen wrote:
> >
> > +#define SGX_NR_TO_SCAN 16
> > +#define SGX_NR_LOW_PAGES 32
> > +#define SGX_NR_HIGH_PAGES 64
> > +
> > bool sgx_enabled __ro_after_init;
> > EXPORT_SYMBOL(sgx_enabled);
> > bool sgx_lc_enabled __ro_after_init;
> > EXPORT_SYMBOL(sgx_lc_enabled);
> > +LIST_HEAD(sgx_active_page_list);
> > +EXPORT_SYMBOL(sgx_active_page_list);
> > +DEFINE_SPINLOCK(sgx_active_page_list_lock);
> > +EXPORT_SYMBOL(sgx_active_page_list_lock);
>
> Why is all of this exported. If done right then no call site has to fiddle
> with the list and the lock at all.
We can fix this in a way that these exports are not needed. Thanks
for pointing this out.
> > static atomic_t sgx_nr_free_pages = ATOMIC_INIT(0);
> > static struct sgx_epc_bank sgx_epc_banks[SGX_MAX_EPC_BANKS];
> > static int sgx_nr_epc_banks;
> > +static struct task_struct *ksgxswapd_tsk;
> > +static DECLARE_WAIT_QUEUE_HEAD(ksgxswapd_waitq);
> > +
> > +static void sgx_swap_cluster(void)
> > +{
> > + struct sgx_epc_page *cluster[SGX_NR_TO_SCAN + 1];
> > + struct sgx_epc_page *epc_page;
> > + int i;
> > + int j;
>
> int i, j;
I've always preferred single declaration per line even for index
variables but not something that I'm going to argue about too
much.
> > + memset(cluster, 0, sizeof(cluster));
> > +
> > + for (i = 0, j = 0; i < SGX_NR_TO_SCAN; i++) {
> > + spin_lock(&sgx_active_page_list_lock);
> > + if (list_empty(&sgx_active_page_list)) {
> > + spin_unlock(&sgx_active_page_list_lock);
> > + break;
> > + }
> > + epc_page = list_first_entry(&sgx_active_page_list,
> > + struct sgx_epc_page, list);
> > + if (!epc_page->impl->ops->get(epc_page)) {
> > + list_move_tail(&epc_page->list, &sgx_active_page_list);
> > + spin_unlock(&sgx_active_page_list_lock);
> > + continue;
> > + }
> > + list_del(&epc_page->list);
> > + spin_unlock(&sgx_active_page_list_lock);
> > +
> > + if (epc_page->impl->ops->reclaim(epc_page)) {
> > + cluster[j++] = epc_page;
> > + } else {
> > + spin_lock(&sgx_active_page_list_lock);
> > + list_add_tail(&epc_page->list, &sgx_active_page_list);
> > + spin_unlock(&sgx_active_page_list_lock);
> > + epc_page->impl->ops->put(epc_page);
> > + }
> > + }
> > +
> > + for (i = 0; cluster[i]; i++) {
> > + epc_page = cluster[i];
> > + epc_page->impl->ops->block(epc_page);
> > + }
> > +
> > + for (i = 0; cluster[i]; i++) {
> > + epc_page = cluster[i];
> > + epc_page->impl->ops->write(epc_page);
> > + epc_page->impl->ops->put(epc_page);
> > + sgx_free_page(epc_page);
> > + }
>
> Thanks a lot for commenting this piece of art thoughtfully. It's entirely
> clear how all of this works now.
Got your point.
> > +}
> > +
> > +static int ksgxswapd(void *p)
> > +{
> > + set_freezable();
> > +
> > + while (!kthread_should_stop()) {
> > + if (try_to_freeze())
> > + continue;
> > +
> > + wait_event_freezable(ksgxswapd_waitq, kthread_should_stop() ||
> > + atomic_read(&sgx_nr_free_pages) <
> > + SGX_NR_HIGH_PAGES);
> > +
> > + if (atomic_read(&sgx_nr_free_pages) < SGX_NR_HIGH_PAGES)
> > + sgx_swap_cluster();
> > + }
> > +
> > + pr_info("%s: done\n", __func__);
>
> Really useful.
Forgotten cruft, will remove.
> > + return 0;
> > +}
> > +
> > +static struct sgx_epc_page *sgx_try_alloc_page(struct sgx_epc_page_impl *impl)
> > +{
> > + struct sgx_epc_bank *bank;
> > + struct sgx_epc_page *page = NULL;
> > + int i;
> > +
> > + for (i = 0; i < sgx_nr_epc_banks; i++) {
> > + bank = &sgx_epc_banks[i];
> > +
> > + down_write(&bank->lock);
> > +
> > + if (atomic_read(&bank->free_cnt))
>
> And these atomics are required becasue bank->lock protection is not
> sufficient or what am I missing here?
This is also response to your comment below. It would be better idea
to just use a spinlock I guess. Seeing your and Daves point.
> > + page = bank->pages[atomic_dec_return(&bank->free_cnt)];
> > +
> > + up_write(&bank->lock);
> > +
> > + if (page)
> > + break;
> > + }
> > +
> > + if (page) {
> > + atomic_dec(&sgx_nr_free_pages);
> > + page->impl = impl;
> > + }
> > +
> > + return page;
> > +}
> > +
> > +/**
> > + * sgx_alloc_page - allocate an EPC page
> > + * @flags: allocation flags
> > + * @impl: implementation for the struct sgx_epc_page
> > + *
> > + * Try to grab a page from the free EPC page list. If there is a free page
> > + * available, it is returned to the caller. If called with SGX_ALLOC_ATOMIC,
> > + * the function will return immediately if the list is empty. Otherwise, it
> > + * will swap pages up until there is a free page available. Upon returning the
> > + * low watermark is checked and ksgxswapd is waken up if we are below it.
> > + *
> > + * Return:
> > + * a &struct sgx_epc_page instace,
> > + * -ENOMEM if all pages are unreclaimable,
> > + * -EBUSY when called with SGX_ALLOC_ATOMIC and out of free pages
> > + */
> > +struct sgx_epc_page *sgx_alloc_page(struct sgx_epc_page_impl *impl,
> > + unsigned int flags)
> > +{
> > + struct sgx_epc_page *entry;
> > +
> > + for ( ; ; ) {
> > + entry = sgx_try_alloc_page(impl);
> > + if (entry)
> > + break;
> > +
> > + if (list_empty(&sgx_active_page_list))
> > + return ERR_PTR(-ENOMEM);
> > +
> > + if (flags & SGX_ALLOC_ATOMIC) {
> > + entry = ERR_PTR(-EBUSY);
> > + break;
> > + }
> > +
> > + if (signal_pending(current)) {
> > + entry = ERR_PTR(-ERESTARTSYS);
> > + break;
> > + }
> > +
> > + sgx_swap_cluster();
> > + schedule();
> > + }
> > +
> > + if (atomic_read(&sgx_nr_free_pages) < SGX_NR_LOW_PAGES)
> > + wake_up(&ksgxswapd_waitq);
>
> What's the logic of SGX_NR_LOW_PAGES vs. SGX_NR_HIGH_PAGES?
If the number of pages goes below SGX_NR_LOW_PAGES ksgxswapd swaps pages
up until SGX_NR_HIGH_PAGES is reached.
>
> > +
> > + return entry;
> > +}
> > +EXPORT_SYMBOL(sgx_alloc_page);
> > +
> > +/**
> > + * sgx_free_page - free an EPC page
> > + *
> > + * @page: any EPC page
> > + *
> > + * Remove an EPC page and insert it back to the list of free pages.
> > + *
> > + * Return: SGX error code
> > + */
> > +int sgx_free_page(struct sgx_epc_page *page)
> > +{
> > + struct sgx_epc_bank *bank = SGX_EPC_BANK(page);
> > + int ret;
> > +
> > + ret = sgx_eremove(page);
> > + if (ret) {
> > + pr_debug("EREMOVE returned %d\n", ret);
> > + return ret;
> > + }
> > +
> > + down_read(&bank->lock);
> > + bank->pages[atomic_inc_return(&bank->free_cnt) - 1] = page;
> > + atomic_inc(&sgx_nr_free_pages);
> > + up_read(&bank->lock);
>
> I have hard time to see the benefit of this reader/writer semaphore
> here. Both sides which fiddle with the bank pages are doing a simple
> de/increment of free_cnt and a store resp. load. So what justifies the
> overhead of a rwsem?
>
> > static __init int sgx_init_epc_bank(unsigned long addr, unsigned long size,
> > unsigned long index,
> > struct sgx_epc_bank *bank)
> > @@ -114,6 +318,11 @@ static __init void sgx_page_cache_teardown(void)
> > kfree(bank->pages);
> > kfree(bank->pages_data);
> > }
> > +
> > + if (ksgxswapd_tsk) {
> > + kthread_stop(ksgxswapd_tsk);
> > + ksgxswapd_tsk = NULL;
>
> This stops the thread _AFTER_ freeing all the bank memory. Is that actually
> correct?
Should not cause any actual regressions but is a flakky order anyway
so I will change it.
/Jarkko
next prev parent reply other threads:[~2018-07-04 18:24 UTC|newest]
Thread overview: 126+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-07-03 18:19 [PATCH v12 00/13] Intel SGX1 support Jarkko Sakkinen
2018-07-03 18:19 ` Jarkko Sakkinen
2018-07-03 18:19 ` Jarkko Sakkinen
2018-07-03 18:19 ` Jarkko Sakkinen
2018-07-03 18:19 ` Jarkko Sakkinen
2018-07-03 18:19 ` [PATCH v12 01/13] x86/sgx: updated MAINTAINERS Jarkko Sakkinen
2018-07-03 18:19 ` Jarkko Sakkinen
2018-07-03 18:19 ` Jarkko Sakkinen
2018-07-03 18:41 ` Thomas Gleixner
2018-07-03 18:41 ` Thomas Gleixner
2018-07-04 17:23 ` Jarkko Sakkinen
2018-07-04 17:23 ` Jarkko Sakkinen
2018-07-03 18:19 ` [PATCH v12 02/13] x86/sgx: add SGX definitions to cpufeature Jarkko Sakkinen
2018-07-03 18:19 ` Jarkko Sakkinen
2018-07-03 18:19 ` Jarkko Sakkinen
2018-07-03 18:48 ` Thomas Gleixner
2018-07-03 18:48 ` Thomas Gleixner
2018-07-04 17:24 ` Jarkko Sakkinen
2018-07-04 17:24 ` Jarkko Sakkinen
2018-07-03 18:19 ` [PATCH v12 03/13] x86/sgx: add SGX definitions to msr-index.h Jarkko Sakkinen
2018-07-03 18:19 ` Jarkko Sakkinen
2018-07-03 18:19 ` Jarkko Sakkinen
2018-07-03 18:31 ` Dave Hansen
2018-07-03 18:31 ` Dave Hansen
2018-07-04 17:25 ` Jarkko Sakkinen
2018-07-04 17:25 ` Jarkko Sakkinen
2018-07-05 16:05 ` Jarkko Sakkinen
2018-07-05 16:05 ` Jarkko Sakkinen
2018-07-05 16:08 ` Jarkko Sakkinen
2018-07-05 16:08 ` Jarkko Sakkinen
2018-07-05 16:09 ` Dave Hansen
2018-07-05 16:09 ` Dave Hansen
2018-07-03 18:51 ` Thomas Gleixner
2018-07-03 18:51 ` Thomas Gleixner
2018-07-04 17:26 ` Jarkko Sakkinen
2018-07-04 17:26 ` Jarkko Sakkinen
2018-07-03 18:19 ` [PATCH v12 04/13] x86/cpufeatures: add Intel-defined SGX leaf CPUID_12_EAX Jarkko Sakkinen
2018-07-03 18:19 ` Jarkko Sakkinen
2018-07-03 18:19 ` Jarkko Sakkinen
2018-07-03 18:54 ` Thomas Gleixner
2018-07-03 18:54 ` Thomas Gleixner
2018-07-03 18:54 ` Thomas Gleixner
2018-07-04 17:27 ` Jarkko Sakkinen
2018-07-04 17:27 ` Jarkko Sakkinen
2018-07-03 18:19 ` [PATCH v12 05/13] x86/sgx: architectural structures Jarkko Sakkinen
2018-07-03 18:19 ` Jarkko Sakkinen
2018-07-03 18:19 ` Jarkko Sakkinen
2018-07-03 19:02 ` Dave Hansen
2018-07-03 19:02 ` Dave Hansen
2018-07-04 18:03 ` Jarkko Sakkinen
2018-07-04 18:03 ` Jarkko Sakkinen
2018-07-03 19:04 ` Thomas Gleixner
2018-07-03 19:04 ` Thomas Gleixner
2018-07-04 18:07 ` Jarkko Sakkinen
2018-07-04 18:07 ` Jarkko Sakkinen
2018-07-03 21:22 ` Dave Hansen
2018-07-03 21:22 ` Dave Hansen
2018-07-04 18:09 ` Jarkko Sakkinen
2018-07-04 18:09 ` Jarkko Sakkinen
2018-07-05 15:31 ` Dave Hansen
2018-07-05 15:31 ` Dave Hansen
2018-07-05 20:09 ` Jarkko Sakkinen
2018-07-05 20:09 ` Jarkko Sakkinen
2018-07-05 21:50 ` hpa
2018-07-05 21:50 ` hpa
2018-07-10 8:06 ` Andy Shevchenko
2018-07-10 8:06 ` Andy Shevchenko
2018-07-10 11:57 ` Thomas Gleixner
2018-07-10 11:57 ` Thomas Gleixner
2018-07-03 18:19 ` [PATCH v12 06/13] x86/sgx: detect Intel SGX Jarkko Sakkinen
2018-07-03 18:19 ` Jarkko Sakkinen
2018-07-03 18:19 ` Jarkko Sakkinen
2018-07-03 19:09 ` Thomas Gleixner
2018-07-03 19:09 ` Thomas Gleixner
2018-07-04 17:28 ` Jarkko Sakkinen
2018-07-04 17:28 ` Jarkko Sakkinen
2018-07-03 18:19 ` [PATCH v12 07/13] x86/sgx: data structures for tracking available EPC pages Jarkko Sakkinen
2018-07-03 18:19 ` Jarkko Sakkinen
2018-07-03 18:19 ` Jarkko Sakkinen
2018-07-03 19:03 ` Dave Hansen
2018-07-03 19:03 ` Dave Hansen
2018-07-04 17:34 ` Jarkko Sakkinen
2018-07-04 17:34 ` Jarkko Sakkinen
2018-07-03 19:46 ` Thomas Gleixner
2018-07-03 19:46 ` Thomas Gleixner
2018-07-03 20:26 ` Randy Dunlap
2018-07-03 20:26 ` Randy Dunlap
2018-07-03 20:44 ` Thomas Gleixner
2018-07-03 20:44 ` Thomas Gleixner
2018-07-04 17:36 ` Jarkko Sakkinen
2018-07-04 17:36 ` Jarkko Sakkinen
2018-07-03 18:19 ` [PATCH v12 08/13] x86/sgx: wrappers for ENCLS opcode leaf functions Jarkko Sakkinen
2018-07-03 18:19 ` Jarkko Sakkinen
2018-07-03 18:19 ` Jarkko Sakkinen
2018-07-03 20:16 ` Thomas Gleixner
2018-07-03 20:16 ` Thomas Gleixner
2018-07-04 17:33 ` Jarkko Sakkinen
2018-07-04 17:33 ` Jarkko Sakkinen
2018-07-03 18:19 ` [PATCH v12 09/13] x86/sgx: EPC page allocation routines Jarkko Sakkinen
2018-07-03 18:19 ` Jarkko Sakkinen
2018-07-03 18:19 ` Jarkko Sakkinen
2018-07-03 20:41 ` Thomas Gleixner
2018-07-03 20:41 ` Thomas Gleixner
2018-07-04 4:25 ` Borislav Petkov
2018-07-04 4:25 ` Borislav Petkov
2018-07-05 18:21 ` Jarkko Sakkinen
2018-07-05 18:21 ` Jarkko Sakkinen
2018-07-04 18:24 ` Jarkko Sakkinen [this message]
2018-07-04 18:24 ` Jarkko Sakkinen
2018-07-03 18:19 ` [PATCH v12 10/13] x86/sgx: sgx_einit() Jarkko Sakkinen
2018-07-03 18:19 ` Jarkko Sakkinen
2018-07-03 18:19 ` Jarkko Sakkinen
2018-07-03 18:19 ` [PATCH v12 11/13] platform/x86: Intel SGX driver Jarkko Sakkinen
2018-07-03 18:19 ` Jarkko Sakkinen
2018-07-03 18:19 ` Jarkko Sakkinen
2018-07-25 15:52 ` Jethro Beekman
2018-07-25 15:52 ` Jethro Beekman
2018-07-28 13:23 ` Jarkko Sakkinen
2018-07-28 13:23 ` Jarkko Sakkinen
2018-07-03 18:19 ` [PATCH v12 12/13] platform/x86: ptrace() support for the " Jarkko Sakkinen
2018-07-03 18:19 ` Jarkko Sakkinen
2018-07-03 18:19 ` Jarkko Sakkinen
2018-07-03 18:19 ` [PATCH v12 13/13] x86/sgx: driver documentation Jarkko Sakkinen
2018-07-03 18:19 ` Jarkko Sakkinen
2018-07-03 18:19 ` Jarkko Sakkinen
2018-07-03 18:19 ` Jarkko Sakkinen
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20180704182419.GO6724@linux.intel.com \
--to=jarkko.sakkinen@linux.intel.com \
--cc=dave.hansen@intel.com \
--cc=hpa@zytor.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-sgx@vger.kernel.org \
--cc=mingo@redhat.com \
--cc=nhorman@redhat.com \
--cc=npmccallum@redhat.com \
--cc=platform-driver-x86@vger.kernel.org \
--cc=sean.j.christopherson@intel.com \
--cc=tglx@linutronix.de \
--cc=x86@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.