[RFC PATCH v8 15/35] x86/apic: Unionize apic regs for 32bit/64bit access w/o type casting

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Define apic_page construct to unionize APIC register 32bit/64bit
accesses and use it in apic_{get|set}*() to avoid using type
casting.

As Secure AVIC APIC driver requires accessing APIC page at byte
offsets (to get an APIC register's bitmap start address), support
byte access granularity in apic_page (in addition to 32-bit and
64-bit accesses).

One caveat of this change is that the generated code is slighly
larger. Below is the code generation for apic_get_reg() using
gcc-14.2:

- Without change:

apic_get_reg:

89 f6       mov    %esi,%esi
8b 04 37    mov    (%rdi,%rsi,1),%eax
c3          ret

- With change:

apic_get_reg:

c1 ee 02    shr    $0x2,%esi
8b 04 b7    mov    (%rdi,%rsi,4),%eax
c3          ret

lapic.o text size change is shown below:

Obj        Old-size      New-size

lapic.o    28800         28832

Signed-off-by: Neeraj Upadhyay <Neeraj.Upadhyay@xxxxxxx>
---
Changes since v7:
 - Commit log update.

 arch/x86/include/asm/apic.h | 25 +++++++++++++++++++++----
 1 file changed, 21 insertions(+), 4 deletions(-)

diff --git a/arch/x86/include/asm/apic.h b/arch/x86/include/asm/apic.h
index 07ba4935e873..b7cbe9ba363e 100644
--- a/arch/x86/include/asm/apic.h
+++ b/arch/x86/include/asm/apic.h
@@ -525,26 +525,43 @@ static inline int apic_find_highest_vector(void *bitmap)
 	return -1;
 }
 
+struct apic_page {
+	union {
+		u64     regs64[PAGE_SIZE / 8];
+		u32     regs[PAGE_SIZE / 4];
+		u8      bytes[PAGE_SIZE];
+	};
+} __aligned(PAGE_SIZE);
+
 static inline u32 apic_get_reg(void *regs, int reg)
 {
-	return *((u32 *) (regs + reg));
+	struct apic_page *ap = regs;
+
+	return ap->regs[reg / 4];
 }
 
 static inline void apic_set_reg(void *regs, int reg, u32 val)
 {
-	*((u32 *) (regs + reg)) = val;
+	struct apic_page *ap = regs;
+
+	ap->regs[reg / 4] = val;
 }
 
 static __always_inline u64 apic_get_reg64(void *regs, int reg)
 {
+	struct apic_page *ap = regs;
+
 	BUILD_BUG_ON(reg != APIC_ICR);
-	return *((u64 *) (regs + reg));
+
+	return ap->regs64[reg / 8];
 }
 
 static __always_inline void apic_set_reg64(void *regs, int reg, u64 val)
 {
+	struct apic_page *ap = regs;
+
 	BUILD_BUG_ON(reg != APIC_ICR);
-	*((u64 *) (regs + reg)) = val;
+	ap->regs64[reg / 8] = val;
 }
 
 static inline void apic_clear_vector(int vec, void *bitmap)
-- 
2.34.1





[Index of Archives]     [KVM ARM]     [KVM ia64]     [KVM ppc]     [Virtualization Tools]     [Spice Development]     [Libvirt]     [Libvirt Users]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite Questions]     [Linux Kernel]     [Linux SCSI]     [XFree86]

  Powered by Linux