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

GIC v3 function gicd_set_ipriorityr funtion is buggy ! need update like above #640

Open
mariusxp opened this issue Oct 24, 2018 · 4 comments
Labels

Comments

@mariusxp
Copy link

void gicd_set_ipriorityr(unsigned int base, unsigned int id, unsigned int pri)
{
//read/modify/write 8 bits
unsigned n = id >> IPRIORITYR_SHIFT;
// select the byte within the word
unsigned int bit_shift = (id & 0x3) << 3;
unsigned int prior_val = GET_REG_WORD_VAL(base + GICD_IPRIORITYR + (n << 2));
prior_val &= ~(GIC_PRI_MASK << bit_shift);
prior_val |= ((pri & GIC_PRI_MASK) << bit_shift);
SET_REG_WORD(base + GICD_IPRIORITYR + (n << 2), prior_val);
}

@mariusxp mariusxp reopened this Oct 24, 2018
@mariusxp mariusxp changed the title gicd_set_ipriorityr funtion is buggy ! need update like above GIC v3 function gicd_set_ipriorityr funtion is buggy ! need update like above Oct 24, 2018
@ghost
Copy link

ghost commented Oct 24, 2018

Why do you need to do the read, mask and write manually? The register is R/W according to ARM Generic Interrupt Controller Architecture Specification (IHI 0069C), so just writing a byte should work.

@mariusxp
Copy link
Author

please read with care the specs:
For interrupt ID m, when DIV and MOD are the integer division and modulo operations:
• The corresponding GICD_IPRIORITYR number, n, is given by n = m DIV 4.
• The offset of the required GICD_IPRIORITYR register is (0x400 + (4*n)).
• The byte offset of the required Priority field in this register is m MOD 4, where:
— Byte offset 0 refers to register bits [7:0].
— Byte offset 1 refers to register bits [15:8].
— Byte offset 2 refers to register bits [23:16].
— Byte offset 3 refers to register bits [31:24].

it is not so easy you pointed it

@ghost
Copy link

ghost commented Oct 26, 2018

Well, but that only means that for interrupt ID m the corresponding address is GICD_IPRIORITYR + id, just explained in a really convoluted way. That explanation considers each register as a 32-bit register. If you consider them as 8-bit registers then it is just like I have explained.

@soby-mathew
Copy link

• The corresponding GICD_IPRIORITYR number, n, is given by n = m DIV 4.
• The offset of the required GICD_IPRIORITYR register is (0x400 + (4*n)).
• The byte offset of the required Priority field in this register is m MOD 4, where:
— Byte offset 0 refers to register bits [7:0].
— Byte offset 1 refers to register bits [15:8].
— Byte offset 2 refers to register bits [23:16].
— Byte offset 3 refers to register bits [31:24].

Yes, its is a bitfield of 4 fields and each field is accessible as a byte. The read-modify-write sequence will not work in a multi core system unless there can be global locking scheme shared across multiple software stacks.

void gicd_set_ipriorityr(uintptr_t base, unsigned int id, unsigned int pri)
{
	uint8_t val = pri & GIC_PRI_MASK;
	mmio_write_8(base + GICD_IPRIORITYR + id, val);
}

Please let us know if you see any corruption of priority values with that implementation.

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

No branches or pull requests

2 participants