mirror of
https://github.com/cirosantilli/linux-kernel-module-cheat.git
synced 2026-01-27 20:14:27 +01:00
fix arm timer baremetal!
This commit is contained in:
@@ -71,7 +71,7 @@ int main(void) {
|
|||||||
printf("&after_svc %p\n", &&after_svc);
|
printf("&after_svc %p\n", &&after_svc);
|
||||||
assert(myvar == 0);
|
assert(myvar == 0);
|
||||||
/* Max 16-bits. */
|
/* Max 16-bits. */
|
||||||
LKMC_SVC(0xABCD);
|
lkmc_svc(0xABCD);
|
||||||
after_svc:
|
after_svc:
|
||||||
assert(myvar == 1);
|
assert(myvar == 1);
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@@ -4,15 +4,25 @@
|
|||||||
#include <lkmc.h>
|
#include <lkmc.h>
|
||||||
#include <lkmc/gicv3.h>
|
#include <lkmc/gicv3.h>
|
||||||
|
|
||||||
#define IRQ_FOUND (0)
|
#define CLOCK_FREQUENCY 10
|
||||||
#define IRQ_NOT_FOUND (1)
|
#define INTERRUPT_FREQUENCY 1
|
||||||
|
|
||||||
void enable_irq(void) {
|
void enable_irq(void) {
|
||||||
__asm__ __volatile__("msr DAIFClr, %0\n\t" : : "i" (LKMC_SYSREG_BITS_DAIF_IRQ) : "memory");
|
__asm__ __volatile__(
|
||||||
|
"msr DAIFClr, %0\n\t"
|
||||||
|
:
|
||||||
|
: "i" (LKMC_SYSREG_BITS_DAIF_IRQ)
|
||||||
|
: "memory"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void disable_irq(void) {
|
void disable_irq(void) {
|
||||||
__asm__ __volatile__("msr DAIFSet, %0\n\t" : : "i" (LKMC_SYSREG_BITS_DAIF_IRQ) : "memory");
|
__asm__ __volatile__(
|
||||||
|
"msr DAIFSet, %0\n\t"
|
||||||
|
:
|
||||||
|
: "i" (LKMC_SYSREG_BITS_DAIF_IRQ)
|
||||||
|
: "memory"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Processor status word. */
|
/* Processor status word. */
|
||||||
@@ -23,6 +33,20 @@ void psw_disable_and_save_interrupt(uint64_t *pswp) {
|
|||||||
*pswp = psw;
|
*pswp = psw;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void disable_cntv(void) {
|
||||||
|
lkmc_sysreg_write_cntv_ctl_el0(
|
||||||
|
lkmc_sysreg_read_cntv_ctl_el0() &
|
||||||
|
LKMC_SYSREG_CNTV_CTL_ENABLE
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void enable_cntv(void) {
|
||||||
|
lkmc_sysreg_write_cntv_ctl_el0(
|
||||||
|
lkmc_sysreg_read_cntv_ctl_el0() |
|
||||||
|
LKMC_SYSREG_CNTV_CTL_ENABLE
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/* Processor status word. */
|
/* Processor status word. */
|
||||||
void psw_restore_interrupt(uint64_t *pswp) {
|
void psw_restore_interrupt(uint64_t *pswp) {
|
||||||
uint64_t psw;
|
uint64_t psw;
|
||||||
@@ -39,7 +63,7 @@ void lkmc_vector_trap_handler(
|
|||||||
if ((exception->exc_type & 0xff) == LKMC_VECTOR_IRQ_SPX) {
|
if ((exception->exc_type & 0xff) == LKMC_VECTOR_IRQ_SPX) {
|
||||||
psw_disable_and_save_interrupt(&psw);
|
psw_disable_and_save_interrupt(&psw);
|
||||||
rc = gic_v3_find_pending_irq(exception, &irq);
|
rc = gic_v3_find_pending_irq(exception, &irq);
|
||||||
if (rc != IRQ_FOUND) {
|
if (rc) {
|
||||||
puts("IRQ not found!");
|
puts("IRQ not found!");
|
||||||
goto restore_irq_out;
|
goto restore_irq_out;
|
||||||
} else {
|
} else {
|
||||||
@@ -47,17 +71,23 @@ void lkmc_vector_trap_handler(
|
|||||||
}
|
}
|
||||||
gicd_disable_int(irq);
|
gicd_disable_int(irq);
|
||||||
gic_v3_eoi(irq);
|
gic_v3_eoi(irq);
|
||||||
printf("CNTVCT_EL0 0x%" PRIX64 "\n", lkmc_sysreg_read_cntvct_el0());
|
// Timer specific stuff.
|
||||||
|
{
|
||||||
|
disable_cntv();
|
||||||
|
gicd_clear_pending(TIMER_IRQ);
|
||||||
|
lkmc_sysreg_print_cntvct_el0();
|
||||||
|
raw_write_cntv_cval_el0(
|
||||||
|
lkmc_sysreg_read_cntvct_el0() +
|
||||||
|
CLOCK_FREQUENCY / INTERRUPT_FREQUENCY
|
||||||
|
);
|
||||||
|
enable_cntv();
|
||||||
|
}
|
||||||
gicd_enable_int(irq);
|
gicd_enable_int(irq);
|
||||||
restore_irq_out:
|
restore_irq_out:
|
||||||
psw_restore_interrupt(&psw);
|
psw_restore_interrupt(&psw);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void enable_cntv(void) {
|
|
||||||
lkmc_sysreg_write_cntv_ctl_el0(lkmc_sysreg_read_cntv_ctl_el0() | LKMC_CNTV_CTL_ENABLE);
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(void) {
|
int main(void) {
|
||||||
/* Initial state. */
|
/* Initial state. */
|
||||||
lkmc_sysreg_print_cntv_ctl_el0();
|
lkmc_sysreg_print_cntv_ctl_el0();
|
||||||
@@ -73,7 +103,7 @@ int main(void) {
|
|||||||
{
|
{
|
||||||
/*uint64_t ticks, current_cnt;*/
|
/*uint64_t ticks, current_cnt;*/
|
||||||
/*uint32_t cntfrq;*/
|
/*uint32_t cntfrq;*/
|
||||||
lkmc_sysreg_write_cntfrq_el0(1);
|
lkmc_sysreg_write_cntfrq_el0(CLOCK_FREQUENCY);
|
||||||
/*ticks = cntfrq;*/
|
/*ticks = cntfrq;*/
|
||||||
/*current_cnt = lkmc_sysreg_read_cntvct_el0();*/
|
/*current_cnt = lkmc_sysreg_read_cntvct_el0();*/
|
||||||
/*lkmc_sysreg_write_cntv_cval_el0(current_cnt + ticks);*/
|
/*lkmc_sysreg_write_cntv_cval_el0(current_cnt + ticks);*/
|
||||||
@@ -81,7 +111,7 @@ int main(void) {
|
|||||||
enable_irq();
|
enable_irq();
|
||||||
}
|
}
|
||||||
while (1) {
|
while (1) {
|
||||||
LKMC_WFI;
|
lkmc_wfi();
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -719,6 +719,8 @@ Incompatible archs are skipped.
|
|||||||
# http://lists.nongnu.org/archive/html/qemu-discuss/2018-08/msg00034.html
|
# http://lists.nongnu.org/archive/html/qemu-discuss/2018-08/msg00034.html
|
||||||
env['machine2'] = 'highmem=off'
|
env['machine2'] = 'highmem=off'
|
||||||
elif env['arch'] == 'aarch64':
|
elif env['arch'] == 'aarch64':
|
||||||
|
# TODO allow the Gic version to be controlled from the CLI.
|
||||||
|
# env['machine2'] = 'gic_version=3'
|
||||||
env['machine2'] = None
|
env['machine2'] = None
|
||||||
else:
|
else:
|
||||||
env['machine2'] = None
|
env['machine2'] = None
|
||||||
|
|||||||
@@ -293,9 +293,9 @@ typedef struct {
|
|||||||
|
|
||||||
void lkmc_vector_trap_handler(LkmcVectorExceptionFrame *exception);
|
void lkmc_vector_trap_handler(LkmcVectorExceptionFrame *exception);
|
||||||
|
|
||||||
/* Mistc assembly instructions. */
|
/* Misc assembly instructions. */
|
||||||
#define LKMC_SVC(immediate) __asm__ __volatile__("svc " #immediate : : : )
|
#define lkmc_svc(immediate) __asm__ __volatile__("svc " #immediate : : : )
|
||||||
#define LKMC_WFI() __asm__ __volatile__ ("wfi" : : : "memory")
|
#define lkmc_wfi() __asm__ __volatile__ ("wfi" : : : "memory")
|
||||||
|
|
||||||
/* Sysreg read and write functions, e.g.:
|
/* Sysreg read and write functions, e.g.:
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -286,8 +286,8 @@ void gic_v3_initialize(void) {
|
|||||||
init_gicd();
|
init_gicd();
|
||||||
init_gicc();
|
init_gicc();
|
||||||
gicd_config(TIMER_IRQ, GIC_GICD_ICFGR_EDGE);
|
gicd_config(TIMER_IRQ, GIC_GICD_ICFGR_EDGE);
|
||||||
gicd_set_priority(TIMER_IRQ, 0 << GIC_PRI_SHIFT ); /* Set priority */
|
gicd_set_priority(TIMER_IRQ, 0 << GIC_PRI_SHIFT);
|
||||||
gicd_set_target(TIMER_IRQ, 0x1); /* processor 0 */
|
gicd_set_target(TIMER_IRQ, 0x1); /* processor 0 */
|
||||||
gicd_clear_pending(TIMER_IRQ);
|
gicd_clear_pending(TIMER_IRQ);
|
||||||
gicd_enable_int(TIMER_IRQ);
|
gicd_enable_int(TIMER_IRQ);
|
||||||
}
|
}
|
||||||
@@ -296,6 +296,7 @@ void gic_v3_initialize(void) {
|
|||||||
/* Find pending IRQ
|
/* Find pending IRQ
|
||||||
* @param[in] exc An exception frame
|
* @param[in] exc An exception frame
|
||||||
* @param[in,out] irqp An IRQ number to be processed
|
* @param[in,out] irqp An IRQ number to be processed
|
||||||
|
* @return 0 if found, 1 if not found
|
||||||
*/
|
*/
|
||||||
int gic_v3_find_pending_irq(
|
int gic_v3_find_pending_irq(
|
||||||
LkmcVectorExceptionFrame *exc __attribute__((unused)),
|
LkmcVectorExceptionFrame *exc __attribute__((unused)),
|
||||||
@@ -305,12 +306,12 @@ int gic_v3_find_pending_irq(
|
|||||||
irq_no i;
|
irq_no i;
|
||||||
for (i = 0; GIC_INT_MAX > i; ++i) {
|
for (i = 0; GIC_INT_MAX > i; ++i) {
|
||||||
if (gicd_probe_pending(i)) {
|
if (gicd_probe_pending(i)) {
|
||||||
rc = 1;
|
rc = 0;
|
||||||
*irqp = i;
|
*irqp = i;
|
||||||
goto found;
|
goto found;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
rc = 0;
|
rc = 1;
|
||||||
found:
|
found:
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user