kernel/x86_64: Use VZEROALL to clear XMM/YMM/etc. registers when available.
It comes with AVX, so enable it if we've enabled AVX. This also adjusts altcodepatch_replace to explicitly set NOPs for the remainder of the patch area. Change-Id: Ia07549851d86836ff5428635b580c751b4e5b2a3 Reviewed-on: https://review.haiku-os.org/c/haiku/+/10867 Reviewed-by: waddlesplash <[email protected]> Reviewed-by: Jérôme Duval <[email protected]> Tested-by: Commit checker robot <[email protected]>
This commit is contained in:
committed by
waddlesplash
parent
009b56e781
commit
facff75dd4
@@ -24,6 +24,7 @@
|
|||||||
#define ALTCODEPATCH_TAG_CLAC 2
|
#define ALTCODEPATCH_TAG_CLAC 2
|
||||||
#define ALTCODEPATCH_TAG_XSAVE 3
|
#define ALTCODEPATCH_TAG_XSAVE 3
|
||||||
#define ALTCODEPATCH_TAG_XRSTOR 4
|
#define ALTCODEPATCH_TAG_XRSTOR 4
|
||||||
|
#define ALTCODEPATCH_TAG_CLEAR_FPU 5
|
||||||
|
|
||||||
|
|
||||||
#ifdef _ASSEMBLER
|
#ifdef _ASSEMBLER
|
||||||
|
|||||||
@@ -118,6 +118,7 @@
|
|||||||
1:
|
1:
|
||||||
|
|
||||||
#define CLEAR_FPU_STATE() \
|
#define CLEAR_FPU_STATE() \
|
||||||
|
CODEPATCH_START \
|
||||||
pxor %xmm0, %xmm0; \
|
pxor %xmm0, %xmm0; \
|
||||||
pxor %xmm1, %xmm1; \
|
pxor %xmm1, %xmm1; \
|
||||||
pxor %xmm2, %xmm2; \
|
pxor %xmm2, %xmm2; \
|
||||||
@@ -133,7 +134,8 @@
|
|||||||
pxor %xmm12, %xmm12; \
|
pxor %xmm12, %xmm12; \
|
||||||
pxor %xmm13, %xmm13; \
|
pxor %xmm13, %xmm13; \
|
||||||
pxor %xmm14, %xmm14; \
|
pxor %xmm14, %xmm14; \
|
||||||
pxor %xmm15, %xmm15
|
pxor %xmm15, %xmm15; \
|
||||||
|
CODEPATCH_END(ALTCODEPATCH_TAG_CLEAR_FPU)
|
||||||
|
|
||||||
// The following code defines the interrupt service routines for all 256
|
// The following code defines the interrupt service routines for all 256
|
||||||
// interrupts. It creates a block of handlers, each 16 bytes, that the IDT
|
// interrupts. It creates a block of handlers, each 16 bytes, that the IDT
|
||||||
|
|||||||
@@ -28,3 +28,7 @@ FUNCTION_END(_xsavec)
|
|||||||
FUNCTION(_xrstor):
|
FUNCTION(_xrstor):
|
||||||
xrstor64 (%rdi)
|
xrstor64 (%rdi)
|
||||||
FUNCTION_END(_xrstor)
|
FUNCTION_END(_xrstor)
|
||||||
|
|
||||||
|
FUNCTION(_vzeroall):
|
||||||
|
vzeroall
|
||||||
|
FUNCTION_END(_vzeroall)
|
||||||
|
|||||||
@@ -45,7 +45,9 @@ arch_altcodepatch_replace(uint16 tag, void* newcodepatch, size_t length)
|
|||||||
void* address = (void*)(KERNEL_LOAD_BASE + patch->kernel_offset);
|
void* address = (void*)(KERNEL_LOAD_BASE + patch->kernel_offset);
|
||||||
if (patch->length < length)
|
if (patch->length < length)
|
||||||
panic("can't copy patch: new code is too long\n");
|
panic("can't copy patch: new code is too long\n");
|
||||||
|
|
||||||
memcpy(address, newcodepatch, length);
|
memcpy(address, newcodepatch, length);
|
||||||
|
memset((uint8*)address + length, 0x90 /* nop */, patch->length - length);
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -88,6 +88,7 @@ extern addr_t _clac;
|
|||||||
extern addr_t _xsave;
|
extern addr_t _xsave;
|
||||||
extern addr_t _xsavec;
|
extern addr_t _xsavec;
|
||||||
extern addr_t _xrstor;
|
extern addr_t _xrstor;
|
||||||
|
extern addr_t _vzeroall;
|
||||||
uint64 gXsaveMask;
|
uint64 gXsaveMask;
|
||||||
uint64 gFPUSaveLength = 512;
|
uint64 gFPUSaveLength = 512;
|
||||||
bool gHasXsave = false;
|
bool gHasXsave = false;
|
||||||
@@ -1944,6 +1945,9 @@ arch_cpu_init_post_vm(kernel_args* args)
|
|||||||
arch_altcodepatch_replace(ALTCODEPATCH_TAG_XRSTOR,
|
arch_altcodepatch_replace(ALTCODEPATCH_TAG_XRSTOR,
|
||||||
&_xrstor, 4);
|
&_xrstor, 4);
|
||||||
|
|
||||||
|
if ((gXsaveMask & IA32_XCR0_AVX) != 0)
|
||||||
|
arch_altcodepatch_replace(ALTCODEPATCH_TAG_CLEAR_FPU, &_vzeroall, 3);
|
||||||
|
|
||||||
dprintf("enable %s 0x%" B_PRIx64 " %" B_PRId64 "\n",
|
dprintf("enable %s 0x%" B_PRIx64 " %" B_PRId64 "\n",
|
||||||
gHasXsavec ? "XSAVEC" : "XSAVE", gXsaveMask, gFPUSaveLength);
|
gHasXsavec ? "XSAVEC" : "XSAVE", gXsaveMask, gFPUSaveLength);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user