mirror of
https://github.com/AsahiLinux/m1n1
synced 2024-11-26 16:30:17 +00:00
m1n1.hv: Always continue on the stepped thread
Signed-off-by: Akihiko Odaki <akihiko.odaki@gmail.com>
This commit is contained in:
parent
6babf39184
commit
bcbe26d79b
7 changed files with 45 additions and 14 deletions
|
@ -126,7 +126,6 @@ class HV(Reloadable):
|
||||||
self.vbar_el1 = None
|
self.vbar_el1 = None
|
||||||
self.want_vbar = None
|
self.want_vbar = None
|
||||||
self.vectors = [None]
|
self.vectors = [None]
|
||||||
self._stepping = False
|
|
||||||
self._bps = [None, None, None, None, None]
|
self._bps = [None, None, None, None, None]
|
||||||
self.sym_offset = 0
|
self.sym_offset = 0
|
||||||
self.symbols = []
|
self.symbols = []
|
||||||
|
@ -780,9 +779,7 @@ class HV(Reloadable):
|
||||||
continue
|
continue
|
||||||
self.u.msr(DBGBCRn_EL1(i), DBGBCR(E=1, PMC=0b11, BAS=0xf).value)
|
self.u.msr(DBGBCRn_EL1(i), DBGBCR(E=1, PMC=0b11, BAS=0xf).value)
|
||||||
|
|
||||||
if not self._stepping:
|
return True
|
||||||
return True
|
|
||||||
self._stepping = False
|
|
||||||
|
|
||||||
def handle_break(self, ctx):
|
def handle_break(self, ctx):
|
||||||
# disable all breakpoints so that we don't get stuck
|
# disable all breakpoints so that we don't get stuck
|
||||||
|
@ -998,8 +995,9 @@ class HV(Reloadable):
|
||||||
def step(self):
|
def step(self):
|
||||||
self.u.msr(MDSCR_EL1, MDSCR(SS=1, MDE=1).value)
|
self.u.msr(MDSCR_EL1, MDSCR(SS=1, MDE=1).value)
|
||||||
self.ctx.spsr.SS = 1
|
self.ctx.spsr.SS = 1
|
||||||
self._stepping = True
|
self.p.hv_pin_cpu(self.ctx.cpu_id)
|
||||||
raise shell.ExitConsole(EXC_RET.HANDLED)
|
self._switch_context()
|
||||||
|
self.p.hv_pin_cpu(0xffffffffffffffff)
|
||||||
|
|
||||||
def _switch_context(self, exit=EXC_RET.HANDLED):
|
def _switch_context(self, exit=EXC_RET.HANDLED):
|
||||||
# Flush current CPU context out to HV
|
# Flush current CPU context out to HV
|
||||||
|
|
|
@ -583,6 +583,7 @@ class M1N1Proxy(Reloadable):
|
||||||
P_HV_START_SECONDARY = 0xc08
|
P_HV_START_SECONDARY = 0xc08
|
||||||
P_HV_SWITCH_CPU = 0xc09
|
P_HV_SWITCH_CPU = 0xc09
|
||||||
P_HV_SET_TIME_STEALING = 0xc0a
|
P_HV_SET_TIME_STEALING = 0xc0a
|
||||||
|
P_HV_PIN_CPU = 0xc0b
|
||||||
|
|
||||||
P_FB_INIT = 0xd00
|
P_FB_INIT = 0xd00
|
||||||
P_FB_SHUTDOWN = 0xd01
|
P_FB_SHUTDOWN = 0xd01
|
||||||
|
@ -1007,6 +1008,8 @@ class M1N1Proxy(Reloadable):
|
||||||
return self.request(self.P_HV_SWITCH_CPU, cpu)
|
return self.request(self.P_HV_SWITCH_CPU, cpu)
|
||||||
def hv_set_time_stealing(self, enabled):
|
def hv_set_time_stealing(self, enabled):
|
||||||
return self.request(self.P_HV_SET_TIME_STEALING, int(bool(enabled)))
|
return self.request(self.P_HV_SET_TIME_STEALING, int(bool(enabled)))
|
||||||
|
def hv_pin_cpu(self, cpu):
|
||||||
|
return self.request(self.P_HV_PIN_CPU, cpu)
|
||||||
|
|
||||||
def fb_init(self):
|
def fb_init(self):
|
||||||
return self.request(self.P_FB_INIT)
|
return self.request(self.P_FB_INIT)
|
||||||
|
|
10
src/hv.c
10
src/hv.c
|
@ -23,6 +23,7 @@ extern char _hv_vectors_start[0];
|
||||||
|
|
||||||
u64 hv_tick_interval;
|
u64 hv_tick_interval;
|
||||||
|
|
||||||
|
int hv_pinned_cpu;
|
||||||
int hv_want_cpu;
|
int hv_want_cpu;
|
||||||
|
|
||||||
static bool hv_should_exit;
|
static bool hv_should_exit;
|
||||||
|
@ -118,6 +119,7 @@ void hv_start(void *entry, u64 regs[4])
|
||||||
hv_secondary_info.gxf_config = mrs(SYS_IMP_APL_GXF_CONFIG_EL1);
|
hv_secondary_info.gxf_config = mrs(SYS_IMP_APL_GXF_CONFIG_EL1);
|
||||||
|
|
||||||
hv_arm_tick();
|
hv_arm_tick();
|
||||||
|
hv_pinned_cpu = -1;
|
||||||
hv_want_cpu = -1;
|
hv_want_cpu = -1;
|
||||||
hv_cpus_in_guest = 1;
|
hv_cpus_in_guest = 1;
|
||||||
|
|
||||||
|
@ -233,6 +235,11 @@ bool hv_switch_cpu(int cpu)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void hv_pin_cpu(int cpu)
|
||||||
|
{
|
||||||
|
hv_pinned_cpu = cpu;
|
||||||
|
}
|
||||||
|
|
||||||
void hv_write_hcr(u64 val)
|
void hv_write_hcr(u64 val)
|
||||||
{
|
{
|
||||||
if (gxf_enabled() && !in_gl12())
|
if (gxf_enabled() && !in_gl12())
|
||||||
|
@ -315,7 +322,8 @@ void hv_tick(struct exc_info *ctx)
|
||||||
hv_wdt_pet();
|
hv_wdt_pet();
|
||||||
iodev_handle_events(uartproxy_iodev);
|
iodev_handle_events(uartproxy_iodev);
|
||||||
if (iodev_can_read(uartproxy_iodev)) {
|
if (iodev_can_read(uartproxy_iodev)) {
|
||||||
hv_exc_proxy(ctx, START_HV, HV_USER_INTERRUPT, NULL);
|
if (hv_pinned_cpu == -1 || hv_pinned_cpu == smp_id())
|
||||||
|
hv_exc_proxy(ctx, START_HV, HV_USER_INTERRUPT, NULL);
|
||||||
}
|
}
|
||||||
hv_vuart_poll();
|
hv_vuart_poll();
|
||||||
}
|
}
|
||||||
|
|
1
src/hv.h
1
src/hv.h
|
@ -97,6 +97,7 @@ void hv_start(void *entry, u64 regs[4]);
|
||||||
void hv_start_secondary(int cpu, void *entry, u64 regs[4]);
|
void hv_start_secondary(int cpu, void *entry, u64 regs[4]);
|
||||||
void hv_rendezvous(void);
|
void hv_rendezvous(void);
|
||||||
bool hv_switch_cpu(int cpu);
|
bool hv_switch_cpu(int cpu);
|
||||||
|
void hv_pin_cpu(int cpu);
|
||||||
void hv_arm_tick(void);
|
void hv_arm_tick(void);
|
||||||
void hv_rearm(void);
|
void hv_rearm(void);
|
||||||
void hv_maybe_exit(void);
|
void hv_maybe_exit(void);
|
||||||
|
|
31
src/hv_exc.c
31
src/hv_exc.c
|
@ -37,6 +37,7 @@ static u64 stolen_time = 0;
|
||||||
static u64 exc_entry_time;
|
static u64 exc_entry_time;
|
||||||
|
|
||||||
extern u32 hv_cpus_in_guest;
|
extern u32 hv_cpus_in_guest;
|
||||||
|
extern int hv_pinned_cpu;
|
||||||
extern int hv_want_cpu;
|
extern int hv_want_cpu;
|
||||||
|
|
||||||
static bool time_stealing = true;
|
static bool time_stealing = true;
|
||||||
|
@ -111,10 +112,22 @@ static void hv_maybe_switch_cpu(struct exc_info *ctx, uartproxy_boot_reason_t re
|
||||||
void hv_exc_proxy(struct exc_info *ctx, uartproxy_boot_reason_t reason, u32 type, void *extra)
|
void hv_exc_proxy(struct exc_info *ctx, uartproxy_boot_reason_t reason, u32 type, void *extra)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* If we end up in the proxy due to an event while the host is trying to switch CPUs,
|
* Wait while another CPU is pinned or being switched to.
|
||||||
* handle it as a CPU switch first. We still tell the host the real reason code, though.
|
* If a CPU switch is requested, handle it before actually handling the
|
||||||
|
* exception. We still tell the host the real reason code, though.
|
||||||
*/
|
*/
|
||||||
hv_maybe_switch_cpu(ctx, reason, type, extra);
|
while ((hv_pinned_cpu != -1 && hv_pinned_cpu != smp_id()) || hv_want_cpu != -1) {
|
||||||
|
if (hv_want_cpu == smp_id()) {
|
||||||
|
hv_want_cpu = -1;
|
||||||
|
_hv_exc_proxy(ctx, reason, type, extra);
|
||||||
|
} else {
|
||||||
|
// Unlock the HV so the target CPU can get into the proxy
|
||||||
|
spin_unlock(&bhl);
|
||||||
|
while ((hv_pinned_cpu != -1 && hv_pinned_cpu != smp_id()) || hv_want_cpu != -1)
|
||||||
|
sysop("dmb sy");
|
||||||
|
spin_lock(&bhl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Handle the actual exception */
|
/* Handle the actual exception */
|
||||||
_hv_exc_proxy(ctx, reason, type, extra);
|
_hv_exc_proxy(ctx, reason, type, extra);
|
||||||
|
@ -424,8 +437,12 @@ void hv_exc_fiq(struct exc_info *ctx)
|
||||||
tick = true;
|
tick = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mrs(TPIDR_EL2) != 0 && !(mrs(ISR_EL1) & 0x40) && hv_want_cpu == -1) {
|
int interruptible_cpu = hv_pinned_cpu;
|
||||||
// Secondary CPU and it was just a timer tick (or spurious), so just update FIQs
|
if (interruptible_cpu == -1)
|
||||||
|
interruptible_cpu = 0;
|
||||||
|
|
||||||
|
if (smp_id() != interruptible_cpu && !(mrs(ISR_EL1) & 0x40) && hv_want_cpu == -1) {
|
||||||
|
// Non-interruptible CPU and it was just a timer tick (or spurious), so just update FIQs
|
||||||
hv_update_fiq();
|
hv_update_fiq();
|
||||||
hv_arm_tick();
|
hv_arm_tick();
|
||||||
return;
|
return;
|
||||||
|
@ -435,9 +452,9 @@ void hv_exc_fiq(struct exc_info *ctx)
|
||||||
hv_wdt_breadcrumb('F');
|
hv_wdt_breadcrumb('F');
|
||||||
hv_exc_entry(ctx);
|
hv_exc_entry(ctx);
|
||||||
|
|
||||||
// Only poll for HV events in CPU 0
|
// Only poll for HV events in the interruptible CPU
|
||||||
if (tick) {
|
if (tick) {
|
||||||
if (mrs(TPIDR_EL2) == 0)
|
if (smp_id() == interruptible_cpu)
|
||||||
hv_tick(ctx);
|
hv_tick(ctx);
|
||||||
hv_arm_tick();
|
hv_arm_tick();
|
||||||
}
|
}
|
||||||
|
|
|
@ -468,6 +468,9 @@ int proxy_process(ProxyRequest *request, ProxyReply *reply)
|
||||||
case P_HV_SET_TIME_STEALING:
|
case P_HV_SET_TIME_STEALING:
|
||||||
hv_set_time_stealing(request->args[0]);
|
hv_set_time_stealing(request->args[0]);
|
||||||
break;
|
break;
|
||||||
|
case P_HV_PIN_CPU:
|
||||||
|
hv_pin_cpu(request->args[0]);
|
||||||
|
break;
|
||||||
|
|
||||||
case P_FB_INIT:
|
case P_FB_INIT:
|
||||||
fb_init(request->args[0]);
|
fb_init(request->args[0]);
|
||||||
|
|
|
@ -128,6 +128,7 @@ typedef enum {
|
||||||
P_HV_START_SECONDARY,
|
P_HV_START_SECONDARY,
|
||||||
P_HV_SWITCH_CPU,
|
P_HV_SWITCH_CPU,
|
||||||
P_HV_SET_TIME_STEALING,
|
P_HV_SET_TIME_STEALING,
|
||||||
|
P_HV_PIN_CPU,
|
||||||
|
|
||||||
P_FB_INIT = 0xd00,
|
P_FB_INIT = 0xd00,
|
||||||
P_FB_SHUTDOWN,
|
P_FB_SHUTDOWN,
|
||||||
|
|
Loading…
Reference in a new issue