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

core: interrupts: add interrupt_release api for reset properties #6907

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

ChenRunyang
Copy link

@ChenRunyang ChenRunyang commented Jun 21, 2024

This patch introduces a interrupt_release API to reset the properties of an interrupt to its previous settings. This functionality is essential for scenarios where a specific interrupt needs to be dynamically set to either Group 1 Secure (G1S) or Group 1 Non-Secure (G1NS) at different times.

Copy link
Contributor

@etienne-lms etienne-lms left a comment

Choose a reason for hiding this comment

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

I've not fully dug into the implication of this feature. That said, here are some comments. Also, I wonder it interrupt_release() would be a better label, rather than interrupt_reset().

* @itr_num Interrupt number to reset
*/
static inline void interrupt_reset(struct itr_chip *chip, size_t itr_num)
{
Copy link
Contributor

Choose a reason for hiding this comment

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

assert(chip->ops->reset)

Copy link
Author

Choose a reason for hiding this comment

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

Done

{
size_t idx = it / NUM_INTS_PER_REG;
uint32_t mask = 1 << (it % NUM_INTS_PER_REG);

Copy link
Contributor

Choose a reason for hiding this comment

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

must check that it >= GIC_SPI_BASE

For consistency, it think this function should also ensures the the interrupt was previously disabled. I think this means git_it_reset() needs a return code.

Copy link
Author

Choose a reason for hiding this comment

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

Checked, if it < GIC_SPI_BASE, it will panic

Copy link
Author

Choose a reason for hiding this comment

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

The API only reset the properties of interrupt, It is not necessary that interrupts have been disabled before. Functionally, the two are not coupled.

Copy link
Contributor

Choose a reason for hiding this comment

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

I'm not sure it's that simple (I'm happy to be proven wrong though). What if the interrupt is active?

@@ -996,6 +1024,26 @@ static void gic_op_raise_sgi(struct itr_chip *chip, size_t it,
gic_it_raise_sgi(gd, it, cpu_mask, ns);
}

static void gic_it_reset(struct gic_data *gd, size_t it)
Copy link
Contributor

Choose a reason for hiding this comment

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

this whole function gic_it_reset() seems supported only when CFG_ARM_GICV3 is enabled.

Copy link
Author

Choose a reason for hiding this comment

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

It also works when CFG_ARM_GICV3 is not enabled, The GIC version affects whether IGROUPMODR is configured.

/*
* interrupt_reset() - Reset the property for an interrupt
* @chip Interrupt controller
* @itr_num Interrupt number to reset
Copy link
Contributor

Choose a reason for hiding this comment

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

This is supported only for SPIs, could you add this information in this inline description comment?

Copy link
Author

Choose a reason for hiding this comment

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

Done

@ChenRunyang ChenRunyang changed the title core: interrupts: add interrupt_reset api for reset properties core: interrupts: add interrupt_release api for reset properties Jun 24, 2024
@ChenRunyang
Copy link
Author

I've not fully dug into the implication of this feature. That said, here are some comments. Also, I wonder it interrupt_release() would be a better label, rather than interrupt_reset().

Replaced the label from interrupt_reset to interrupt_release.

Copy link
Contributor

@jenswi-linaro jenswi-linaro left a comment

Choose a reason for hiding this comment

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

I wonder if this doesn't boil to changing the group assignment of the interrupt id. As long as the interrupt is disabled we could leave it to the previous owner to restore the other properties.

{
struct gic_data *gd = &gic_data;

gd->pre_prio = calloc(gd->max_it + 1, sizeof(*gd->pre_prio));
Copy link
Contributor

Choose a reason for hiding this comment

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

This will only be needed in very specific configurations, but like this, it will impact all configurations. How about keeping this information outside the GIC driver and letting interrupt_release() take the needed parameters to restore the state?

Copy link
Author

Choose a reason for hiding this comment

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

Add the gic_spi_get_prop API to get the interrupt properties, and the interrupt_release need to specify the interrupt attributes as parameters.

size_t idx = it / NUM_INTS_PER_REG;
uint32_t mask = 1 << (it % NUM_INTS_PER_REG);

/* Assigned to group0 */
Copy link
Contributor

Choose a reason for hiding this comment

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

What about group1 interrupts?

Copy link
Author

@ChenRunyang ChenRunyang Jun 25, 2024

Choose a reason for hiding this comment

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

The API is used for change group0 or goup1 secure interrupts to group1 interrupts, so if group1 nonsecure interrupts call this API, it will be asserted

Copy link
Contributor

Choose a reason for hiding this comment

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

GICv3 Group 0 interrupts belong to EL3 so I'm not sure we should do anything with those.

@ChenRunyang
Copy link
Author

I wonder if this doesn't boil to changing the group assignment of the interrupt id. As long as the interrupt is disabled we could leave it to the previous owner to restore the other properties.

Yes, it will change the group assignment of the interrupt id.
Updated the gic_op_release API to accept additional properties as parameters. These settings will be restored to their previous state by the original owner.

size_t idx = it / NUM_INTS_PER_REG;
uint32_t mask = 1 << (it % NUM_INTS_PER_REG);

/* Assigned to group0 */
Copy link
Contributor

Choose a reason for hiding this comment

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

GICv3 Group 0 interrupts belong to EL3 so I'm not sure we should do anything with those.

/* Assigned to group0 */
assert(!(io_read32(gd->gicd_base + GICD_IGROUPR(idx)) & mask));

gic_it_set_cpu_mask(gd, it, cpu_mask);
Copy link
Contributor

Choose a reason for hiding this comment

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

Once the interrupt has been changed to non-secure, the normal can configure it to their liking. How about clearing cpu_mask and setting prio to 0xff to avoid leaking information or unintended state?

Copy link
Author

Choose a reason for hiding this comment

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

It's OK to clear the cpu_mask, but is it possible to set the priority to the Linux kernel's default priority setting of 0xa0?And the current behavior of Kernel setting prio is undefined.

Copy link
Contributor

Choose a reason for hiding this comment

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

Sure, that makes sense.

* @prio Interrupt priority
* @cpu_mask Mask of the CPUs targeted by the interrupt
*/
static inline void interrupt_release(struct itr_chip *chip, size_t itr_num,
Copy link
Contributor

Choose a reason for hiding this comment

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

I know that you have already changed the name of this function once, but wouldn't interrupt_release_to_ns() be more clear?

Copy link
Author

Choose a reason for hiding this comment

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

OK, I will use interrupt_release_to_ns instead of interrupt_release.

* @cpu_mask Mask of the CPUs targeted by the interrupt
*/
static inline void interrupt_release(struct itr_chip *chip, size_t itr_num,
uint8_t prio, uint8_t cpu_mask)
Copy link
Contributor

Choose a reason for hiding this comment

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

The normal world should be able to configure this itself.

@@ -858,6 +888,20 @@ void gic_dump_state(void)
}
}

void gic_spi_get_prop(size_t it, uint8_t *cpu_mask, uint8_t *prio)
Copy link
Contributor

Choose a reason for hiding this comment

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

Why is this function needed?

Copy link
Author

Choose a reason for hiding this comment

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

I want to get property before requesting the IRQ so that it can be used later in the irq_release flow. I will remove this function if the cpu_mask is cleared and the priority set to default value.

{
size_t idx = it / NUM_INTS_PER_REG;
uint32_t mask = 1 << (it % NUM_INTS_PER_REG);

Copy link
Contributor

Choose a reason for hiding this comment

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

I'm not sure it's that simple (I'm happy to be proven wrong though). What if the interrupt is active?

@@ -72,6 +72,8 @@ struct itr_ops {
void (*raise_pi)(struct itr_chip *chip, size_t it);
void (*raise_sgi)(struct itr_chip *chip, size_t it,
uint32_t cpu_mask);
void (*release)(struct itr_chip *chip, size_t it,

Choose a reason for hiding this comment

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

release() is doing other way of add(). so, would it be much clear if they are next to each other?

Copy link
Author

Choose a reason for hiding this comment

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

Thanks for your comment, It's sorted them in descending order by the first letter

@jenswi-linaro
Copy link
Contributor

By the way, rebasing the patches on the latest should take care of the failing test case.

@jenswi-linaro
Copy link
Contributor

Please use rebase instead of merge, we don't accept merges in pull requests.

@ChenRunyang ChenRunyang force-pushed the master branch 4 times, most recently from 6d5dbeb to 0e58e2d Compare July 11, 2024 08:59
Copy link
Contributor

@jenswi-linaro jenswi-linaro left a comment

Choose a reason for hiding this comment

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

With my comment addressed, please apply:
Reviewed-by: Jens Wiklander <[email protected]>

{
struct gic_data *gd = &gic_data;
size_t idx = it / NUM_INTS_PER_REG;
uint32_t mask = 1 << (it % NUM_INTS_PER_REG);
Copy link
Contributor

Choose a reason for hiding this comment

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

Please use the BIT32() macro instead. I know we're doing a bit of both in this file, but using BIT32() is the preferred way.

Copy link
Author

Choose a reason for hiding this comment

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

done


assert(it < gd->max_it && it >= GIC_SPI_BASE);
/* Assert it's already disabled */
assert(!gic_it_is_enabled(gd, it));
Copy link
Contributor

Choose a reason for hiding this comment

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

I wonder if an assertion is enough here. I would rather suggest to return an error code, what do you think?

Copy link
Contributor

Choose a reason for hiding this comment

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

Most errors here either cause an assert or a panic. I don't see how this error is a special case.
What should a caller do on this error that he shouldn't have done already?
This is a static programming error, not a dynamic error like malloc() failing.

Copy link
Author

Choose a reason for hiding this comment

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

done

/* Clear pending status */
io_write32(gd->gicd_base + GICD_ICPENDR(idx), mask);
/* Assign it to NS Group1 */
io_setbits32(gd->gicd_base + GICD_IGROUPR(idx), mask);
Copy link
Contributor

Choose a reason for hiding this comment

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

I think this instruction and the one below should be protected by a lock.

Copy link
Contributor

Choose a reason for hiding this comment

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

I agree, since we're writing to a value register, not a set or clear bits register.
This function is in contrast to void gic_init_donate_sgi_to_ns() used post-boot when more than one core might be active in the secure world.

Copy link
Author

Choose a reason for hiding this comment

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

done

@@ -56,4 +58,7 @@ void gic_init_per_cpu(void);

/* Print GIC state to console */
void gic_dump_state(void);

/* Release the property for a shared peripheral interrupt */
Copy link
Contributor

Choose a reason for hiding this comment

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

Explicitly say that the interrupt is re-assigned to the non-secure interrupt group and its priority reset to GIC_SPI_PRI_NS_EL1.
State also that the interrupt shall be disabled when this function is called.

Copy link
Author

Choose a reason for hiding this comment

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

done

of an interrupt

This patch introduces gic_spi_release_to_ns API to release an interrupt
to Non secure settings. This functionality is essential for scenarios
where a specific interrupt needs to be dynamically set to either Group
1 Secure (G1S) or Group 1 Non-Secure (G1NS) at different times.

Signed-off-by: Runyang Chen <[email protected]>
Reviewed-by: Jens Wiklander <[email protected]>
uint32_t mask = BIT32(it % NUM_INTS_PER_REG);

if (it < gd->max_it && it >= GIC_SPI_BASE)
return TEE_ERROR_OVERFLOW;
Copy link
Contributor

Choose a reason for hiding this comment

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

I suggest TEE_ERROR_BAD_PARAMETERS instead.

@@ -858,6 +860,36 @@ void gic_dump_state(void)
}
}

int gic_spi_release_to_ns(size_t it)
Copy link
Contributor

Choose a reason for hiding this comment

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

s/int/TEE_Result/

Copy link

This pull request has been marked as a stale pull request because it has been open (more than) 30 days with no activity. Remove the stale label or add a comment, otherwise this pull request will automatically be closed in 5 days. Note, that you can always re-open a closed issue at any time.

@github-actions github-actions bot added the Stale label Sep 29, 2024
@etienne-lms
Copy link
Contributor

@ChenRunyang, do you plan to update this P-R?

@github-actions github-actions bot removed the Stale label Oct 4, 2024
Copy link

github-actions bot commented Nov 3, 2024

This pull request has been marked as a stale pull request because it has been open (more than) 30 days with no activity. Remove the stale label or add a comment, otherwise this pull request will automatically be closed in 5 days. Note, that you can always re-open a closed issue at any time.

@github-actions github-actions bot added the Stale label Nov 3, 2024
@ChenRunyang
Copy link
Author

@ChenRunyang, do you plan to update this P-R?

Sorry for late, I've been on vacation recently, I will modify the patch according to your suggestions.

@github-actions github-actions bot removed the Stale label Nov 7, 2024
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.

4 participants