Switch to using the TSC code in i386/i386/tsc.c.
This commit is contained in:
parent
85caad2949
commit
ea4f5a71da
@ -138,9 +138,6 @@ int statclock_disable;
|
||||
#endif
|
||||
u_int timer_freq = TIMER_FREQ;
|
||||
int timer0_max_count;
|
||||
uint64_t tsc_freq;
|
||||
int tsc_is_broken;
|
||||
u_int tsc_present;
|
||||
int wall_cmos_clock; /* wall CMOS clock assumed if != 0 */
|
||||
struct mtx clock_lock;
|
||||
|
||||
@ -173,17 +170,8 @@ static u_char timer2_state;
|
||||
static void (*timer_func)(struct clockframe *frame) = hardclock;
|
||||
|
||||
static unsigned i8254_get_timecount(struct timecounter *tc);
|
||||
static unsigned tsc_get_timecount(struct timecounter *tc);
|
||||
static void set_timer_freq(u_int freq, int intr_freq);
|
||||
|
||||
static struct timecounter tsc_timecounter = {
|
||||
tsc_get_timecount, /* get_timecount */
|
||||
0, /* no poll_pps */
|
||||
~0u, /* counter_mask */
|
||||
0, /* frequency */
|
||||
"TSC" /* name */
|
||||
};
|
||||
|
||||
static struct timecounter i8254_timecounter = {
|
||||
i8254_get_timecount, /* get_timecount */
|
||||
0, /* no poll_pps */
|
||||
@ -592,7 +580,6 @@ readrtc(int port)
|
||||
static u_int
|
||||
calibrate_clocks(void)
|
||||
{
|
||||
u_int64_t old_tsc;
|
||||
u_int count, prev_count, tot_count;
|
||||
int sec, start_sec, timeout;
|
||||
|
||||
@ -630,11 +617,6 @@ calibrate_clocks(void)
|
||||
goto fail;
|
||||
tot_count = 0;
|
||||
|
||||
if (tsc_present)
|
||||
old_tsc = rdtsc();
|
||||
else
|
||||
old_tsc = 0; /* shut up gcc */
|
||||
|
||||
/*
|
||||
* Wait for the mc146818A seconds counter to change. Read the i8254
|
||||
* counter for each iteration since this is convenient and only
|
||||
@ -663,16 +645,7 @@ calibrate_clocks(void)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/*
|
||||
* Read the cpu cycle counter. The timing considerations are
|
||||
* similar to those for the i8254 clock.
|
||||
*/
|
||||
if (tsc_present)
|
||||
tsc_freq = rdtsc() - old_tsc;
|
||||
|
||||
if (bootverbose) {
|
||||
if (tsc_present)
|
||||
printf("TSC clock: %ju Hz, ", (intmax_t)tsc_freq);
|
||||
printf("i8254 clock: %u Hz\n", tot_count);
|
||||
}
|
||||
return (tot_count);
|
||||
@ -747,11 +720,6 @@ startrtclock()
|
||||
{
|
||||
u_int delta, freq;
|
||||
|
||||
if (cpu_feature & CPUID_TSC)
|
||||
tsc_present = 1;
|
||||
else
|
||||
tsc_present = 0;
|
||||
|
||||
writertc(RTC_STATUSA, rtc_statusa);
|
||||
writertc(RTC_STATUSB, RTCSB_24HR);
|
||||
|
||||
@ -785,68 +753,13 @@ startrtclock()
|
||||
printf(
|
||||
"%d Hz differs from default of %d Hz by more than 1%%\n",
|
||||
freq, timer_freq);
|
||||
tsc_freq = 0;
|
||||
}
|
||||
|
||||
set_timer_freq(timer_freq, hz);
|
||||
i8254_timecounter.tc_frequency = timer_freq;
|
||||
tc_init(&i8254_timecounter);
|
||||
|
||||
#ifndef CLK_USE_TSC_CALIBRATION
|
||||
if (tsc_freq != 0) {
|
||||
if (bootverbose)
|
||||
printf(
|
||||
"CLK_USE_TSC_CALIBRATION not specified - using old calibration method\n");
|
||||
tsc_freq = 0;
|
||||
}
|
||||
#endif
|
||||
if (tsc_present && tsc_freq == 0) {
|
||||
/*
|
||||
* Calibration of the i586 clock relative to the mc146818A
|
||||
* clock failed. Do a less accurate calibration relative
|
||||
* to the i8254 clock.
|
||||
*/
|
||||
u_int64_t old_tsc = rdtsc();
|
||||
|
||||
DELAY(1000000);
|
||||
tsc_freq = rdtsc() - old_tsc;
|
||||
#ifdef CLK_USE_TSC_CALIBRATION
|
||||
if (bootverbose)
|
||||
printf("TSC clock: %ju Hz (Method B)\n",
|
||||
(intmax_t)tsc_freq);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if !defined(SMP)
|
||||
/*
|
||||
* We can not use the TSC in SMP mode, until we figure out a
|
||||
* cheap (impossible), reliable and precise (yeah right!) way
|
||||
* to synchronize the TSCs of all the CPUs.
|
||||
* Curse Intel for leaving the counter out of the I/O APIC.
|
||||
*/
|
||||
|
||||
/*
|
||||
* We can not use the TSC if we support APM. Precise timekeeping
|
||||
* on an APM'ed machine is at best a fools pursuit, since
|
||||
* any and all of the time spent in various SMM code can't
|
||||
* be reliably accounted for. Reading the RTC is your only
|
||||
* source of reliable time info. The i8254 looses too of course
|
||||
* but we need to have some kind of time...
|
||||
* We don't know at this point whether APM is going to be used
|
||||
* or not, nor when it might be activated. Play it safe.
|
||||
*/
|
||||
if (power_pm_get_type() == POWER_PM_TYPE_APM) {
|
||||
if (bootverbose)
|
||||
printf("TSC initialization skipped: APM enabled.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (tsc_present && tsc_freq != 0 && !tsc_is_broken) {
|
||||
tsc_timecounter.tc_frequency = tsc_freq;
|
||||
tc_init(&tsc_timecounter);
|
||||
}
|
||||
|
||||
#endif /* !defined(SMP) */
|
||||
init_TSC();
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1218,26 +1131,6 @@ sysctl_machdep_i8254_freq(SYSCTL_HANDLER_ARGS)
|
||||
SYSCTL_PROC(_machdep, OID_AUTO, i8254_freq, CTLTYPE_INT | CTLFLAG_RW,
|
||||
0, sizeof(u_int), sysctl_machdep_i8254_freq, "IU", "");
|
||||
|
||||
static int
|
||||
sysctl_machdep_tsc_freq(SYSCTL_HANDLER_ARGS)
|
||||
{
|
||||
int error;
|
||||
uint64_t freq;
|
||||
|
||||
if (tsc_timecounter.tc_frequency == 0)
|
||||
return (EOPNOTSUPP);
|
||||
freq = tsc_freq;
|
||||
error = sysctl_handle_int(oidp, &freq, sizeof(freq), req);
|
||||
if (error == 0 && req->newptr != NULL) {
|
||||
tsc_freq = freq;
|
||||
tsc_timecounter.tc_frequency = tsc_freq;
|
||||
}
|
||||
return (error);
|
||||
}
|
||||
|
||||
SYSCTL_PROC(_machdep, OID_AUTO, tsc_freq, CTLTYPE_QUAD | CTLFLAG_RW,
|
||||
0, sizeof(u_int), sysctl_machdep_tsc_freq, "IU", "");
|
||||
|
||||
static unsigned
|
||||
i8254_get_timecount(struct timecounter *tc)
|
||||
{
|
||||
@ -1274,12 +1167,6 @@ i8254_get_timecount(struct timecounter *tc)
|
||||
return (count);
|
||||
}
|
||||
|
||||
static unsigned
|
||||
tsc_get_timecount(struct timecounter *tc)
|
||||
{
|
||||
return (rdtsc());
|
||||
}
|
||||
|
||||
#ifdef DEV_ISA
|
||||
/*
|
||||
* Attach to the ISA PnP descriptors for the timer and realtime clock.
|
||||
|
@ -231,6 +231,7 @@ i386/i386/pmap.c standard
|
||||
i386/i386/support.s standard
|
||||
i386/i386/swtch.s standard
|
||||
i386/i386/sys_machdep.c standard
|
||||
i386/i386/tsc.c standard
|
||||
i386/i386/trap.c standard
|
||||
i386/i386/vm86.c standard
|
||||
i386/i386/vm_machdep.c standard
|
||||
|
@ -138,9 +138,6 @@ int statclock_disable;
|
||||
#endif
|
||||
u_int timer_freq = TIMER_FREQ;
|
||||
int timer0_max_count;
|
||||
uint64_t tsc_freq;
|
||||
int tsc_is_broken;
|
||||
u_int tsc_present;
|
||||
int wall_cmos_clock; /* wall CMOS clock assumed if != 0 */
|
||||
struct mtx clock_lock;
|
||||
|
||||
@ -173,17 +170,8 @@ static u_char timer2_state;
|
||||
static void (*timer_func)(struct clockframe *frame) = hardclock;
|
||||
|
||||
static unsigned i8254_get_timecount(struct timecounter *tc);
|
||||
static unsigned tsc_get_timecount(struct timecounter *tc);
|
||||
static void set_timer_freq(u_int freq, int intr_freq);
|
||||
|
||||
static struct timecounter tsc_timecounter = {
|
||||
tsc_get_timecount, /* get_timecount */
|
||||
0, /* no poll_pps */
|
||||
~0u, /* counter_mask */
|
||||
0, /* frequency */
|
||||
"TSC" /* name */
|
||||
};
|
||||
|
||||
static struct timecounter i8254_timecounter = {
|
||||
i8254_get_timecount, /* get_timecount */
|
||||
0, /* no poll_pps */
|
||||
@ -592,7 +580,6 @@ readrtc(int port)
|
||||
static u_int
|
||||
calibrate_clocks(void)
|
||||
{
|
||||
u_int64_t old_tsc;
|
||||
u_int count, prev_count, tot_count;
|
||||
int sec, start_sec, timeout;
|
||||
|
||||
@ -630,11 +617,6 @@ calibrate_clocks(void)
|
||||
goto fail;
|
||||
tot_count = 0;
|
||||
|
||||
if (tsc_present)
|
||||
old_tsc = rdtsc();
|
||||
else
|
||||
old_tsc = 0; /* shut up gcc */
|
||||
|
||||
/*
|
||||
* Wait for the mc146818A seconds counter to change. Read the i8254
|
||||
* counter for each iteration since this is convenient and only
|
||||
@ -663,16 +645,7 @@ calibrate_clocks(void)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/*
|
||||
* Read the cpu cycle counter. The timing considerations are
|
||||
* similar to those for the i8254 clock.
|
||||
*/
|
||||
if (tsc_present)
|
||||
tsc_freq = rdtsc() - old_tsc;
|
||||
|
||||
if (bootverbose) {
|
||||
if (tsc_present)
|
||||
printf("TSC clock: %ju Hz, ", (intmax_t)tsc_freq);
|
||||
printf("i8254 clock: %u Hz\n", tot_count);
|
||||
}
|
||||
return (tot_count);
|
||||
@ -747,11 +720,6 @@ startrtclock()
|
||||
{
|
||||
u_int delta, freq;
|
||||
|
||||
if (cpu_feature & CPUID_TSC)
|
||||
tsc_present = 1;
|
||||
else
|
||||
tsc_present = 0;
|
||||
|
||||
writertc(RTC_STATUSA, rtc_statusa);
|
||||
writertc(RTC_STATUSB, RTCSB_24HR);
|
||||
|
||||
@ -785,68 +753,13 @@ startrtclock()
|
||||
printf(
|
||||
"%d Hz differs from default of %d Hz by more than 1%%\n",
|
||||
freq, timer_freq);
|
||||
tsc_freq = 0;
|
||||
}
|
||||
|
||||
set_timer_freq(timer_freq, hz);
|
||||
i8254_timecounter.tc_frequency = timer_freq;
|
||||
tc_init(&i8254_timecounter);
|
||||
|
||||
#ifndef CLK_USE_TSC_CALIBRATION
|
||||
if (tsc_freq != 0) {
|
||||
if (bootverbose)
|
||||
printf(
|
||||
"CLK_USE_TSC_CALIBRATION not specified - using old calibration method\n");
|
||||
tsc_freq = 0;
|
||||
}
|
||||
#endif
|
||||
if (tsc_present && tsc_freq == 0) {
|
||||
/*
|
||||
* Calibration of the i586 clock relative to the mc146818A
|
||||
* clock failed. Do a less accurate calibration relative
|
||||
* to the i8254 clock.
|
||||
*/
|
||||
u_int64_t old_tsc = rdtsc();
|
||||
|
||||
DELAY(1000000);
|
||||
tsc_freq = rdtsc() - old_tsc;
|
||||
#ifdef CLK_USE_TSC_CALIBRATION
|
||||
if (bootverbose)
|
||||
printf("TSC clock: %ju Hz (Method B)\n",
|
||||
(intmax_t)tsc_freq);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if !defined(SMP)
|
||||
/*
|
||||
* We can not use the TSC in SMP mode, until we figure out a
|
||||
* cheap (impossible), reliable and precise (yeah right!) way
|
||||
* to synchronize the TSCs of all the CPUs.
|
||||
* Curse Intel for leaving the counter out of the I/O APIC.
|
||||
*/
|
||||
|
||||
/*
|
||||
* We can not use the TSC if we support APM. Precise timekeeping
|
||||
* on an APM'ed machine is at best a fools pursuit, since
|
||||
* any and all of the time spent in various SMM code can't
|
||||
* be reliably accounted for. Reading the RTC is your only
|
||||
* source of reliable time info. The i8254 looses too of course
|
||||
* but we need to have some kind of time...
|
||||
* We don't know at this point whether APM is going to be used
|
||||
* or not, nor when it might be activated. Play it safe.
|
||||
*/
|
||||
if (power_pm_get_type() == POWER_PM_TYPE_APM) {
|
||||
if (bootverbose)
|
||||
printf("TSC initialization skipped: APM enabled.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (tsc_present && tsc_freq != 0 && !tsc_is_broken) {
|
||||
tsc_timecounter.tc_frequency = tsc_freq;
|
||||
tc_init(&tsc_timecounter);
|
||||
}
|
||||
|
||||
#endif /* !defined(SMP) */
|
||||
init_TSC();
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1218,26 +1131,6 @@ sysctl_machdep_i8254_freq(SYSCTL_HANDLER_ARGS)
|
||||
SYSCTL_PROC(_machdep, OID_AUTO, i8254_freq, CTLTYPE_INT | CTLFLAG_RW,
|
||||
0, sizeof(u_int), sysctl_machdep_i8254_freq, "IU", "");
|
||||
|
||||
static int
|
||||
sysctl_machdep_tsc_freq(SYSCTL_HANDLER_ARGS)
|
||||
{
|
||||
int error;
|
||||
uint64_t freq;
|
||||
|
||||
if (tsc_timecounter.tc_frequency == 0)
|
||||
return (EOPNOTSUPP);
|
||||
freq = tsc_freq;
|
||||
error = sysctl_handle_int(oidp, &freq, sizeof(freq), req);
|
||||
if (error == 0 && req->newptr != NULL) {
|
||||
tsc_freq = freq;
|
||||
tsc_timecounter.tc_frequency = tsc_freq;
|
||||
}
|
||||
return (error);
|
||||
}
|
||||
|
||||
SYSCTL_PROC(_machdep, OID_AUTO, tsc_freq, CTLTYPE_QUAD | CTLFLAG_RW,
|
||||
0, sizeof(u_int), sysctl_machdep_tsc_freq, "IU", "");
|
||||
|
||||
static unsigned
|
||||
i8254_get_timecount(struct timecounter *tc)
|
||||
{
|
||||
@ -1274,12 +1167,6 @@ i8254_get_timecount(struct timecounter *tc)
|
||||
return (count);
|
||||
}
|
||||
|
||||
static unsigned
|
||||
tsc_get_timecount(struct timecounter *tc)
|
||||
{
|
||||
return (rdtsc());
|
||||
}
|
||||
|
||||
#ifdef DEV_ISA
|
||||
/*
|
||||
* Attach to the ISA PnP descriptors for the timer and realtime clock.
|
||||
|
115
sys/isa/atrtc.c
115
sys/isa/atrtc.c
@ -138,9 +138,6 @@ int statclock_disable;
|
||||
#endif
|
||||
u_int timer_freq = TIMER_FREQ;
|
||||
int timer0_max_count;
|
||||
uint64_t tsc_freq;
|
||||
int tsc_is_broken;
|
||||
u_int tsc_present;
|
||||
int wall_cmos_clock; /* wall CMOS clock assumed if != 0 */
|
||||
struct mtx clock_lock;
|
||||
|
||||
@ -173,17 +170,8 @@ static u_char timer2_state;
|
||||
static void (*timer_func)(struct clockframe *frame) = hardclock;
|
||||
|
||||
static unsigned i8254_get_timecount(struct timecounter *tc);
|
||||
static unsigned tsc_get_timecount(struct timecounter *tc);
|
||||
static void set_timer_freq(u_int freq, int intr_freq);
|
||||
|
||||
static struct timecounter tsc_timecounter = {
|
||||
tsc_get_timecount, /* get_timecount */
|
||||
0, /* no poll_pps */
|
||||
~0u, /* counter_mask */
|
||||
0, /* frequency */
|
||||
"TSC" /* name */
|
||||
};
|
||||
|
||||
static struct timecounter i8254_timecounter = {
|
||||
i8254_get_timecount, /* get_timecount */
|
||||
0, /* no poll_pps */
|
||||
@ -592,7 +580,6 @@ readrtc(int port)
|
||||
static u_int
|
||||
calibrate_clocks(void)
|
||||
{
|
||||
u_int64_t old_tsc;
|
||||
u_int count, prev_count, tot_count;
|
||||
int sec, start_sec, timeout;
|
||||
|
||||
@ -630,11 +617,6 @@ calibrate_clocks(void)
|
||||
goto fail;
|
||||
tot_count = 0;
|
||||
|
||||
if (tsc_present)
|
||||
old_tsc = rdtsc();
|
||||
else
|
||||
old_tsc = 0; /* shut up gcc */
|
||||
|
||||
/*
|
||||
* Wait for the mc146818A seconds counter to change. Read the i8254
|
||||
* counter for each iteration since this is convenient and only
|
||||
@ -663,16 +645,7 @@ calibrate_clocks(void)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/*
|
||||
* Read the cpu cycle counter. The timing considerations are
|
||||
* similar to those for the i8254 clock.
|
||||
*/
|
||||
if (tsc_present)
|
||||
tsc_freq = rdtsc() - old_tsc;
|
||||
|
||||
if (bootverbose) {
|
||||
if (tsc_present)
|
||||
printf("TSC clock: %ju Hz, ", (intmax_t)tsc_freq);
|
||||
printf("i8254 clock: %u Hz\n", tot_count);
|
||||
}
|
||||
return (tot_count);
|
||||
@ -747,11 +720,6 @@ startrtclock()
|
||||
{
|
||||
u_int delta, freq;
|
||||
|
||||
if (cpu_feature & CPUID_TSC)
|
||||
tsc_present = 1;
|
||||
else
|
||||
tsc_present = 0;
|
||||
|
||||
writertc(RTC_STATUSA, rtc_statusa);
|
||||
writertc(RTC_STATUSB, RTCSB_24HR);
|
||||
|
||||
@ -785,68 +753,13 @@ startrtclock()
|
||||
printf(
|
||||
"%d Hz differs from default of %d Hz by more than 1%%\n",
|
||||
freq, timer_freq);
|
||||
tsc_freq = 0;
|
||||
}
|
||||
|
||||
set_timer_freq(timer_freq, hz);
|
||||
i8254_timecounter.tc_frequency = timer_freq;
|
||||
tc_init(&i8254_timecounter);
|
||||
|
||||
#ifndef CLK_USE_TSC_CALIBRATION
|
||||
if (tsc_freq != 0) {
|
||||
if (bootverbose)
|
||||
printf(
|
||||
"CLK_USE_TSC_CALIBRATION not specified - using old calibration method\n");
|
||||
tsc_freq = 0;
|
||||
}
|
||||
#endif
|
||||
if (tsc_present && tsc_freq == 0) {
|
||||
/*
|
||||
* Calibration of the i586 clock relative to the mc146818A
|
||||
* clock failed. Do a less accurate calibration relative
|
||||
* to the i8254 clock.
|
||||
*/
|
||||
u_int64_t old_tsc = rdtsc();
|
||||
|
||||
DELAY(1000000);
|
||||
tsc_freq = rdtsc() - old_tsc;
|
||||
#ifdef CLK_USE_TSC_CALIBRATION
|
||||
if (bootverbose)
|
||||
printf("TSC clock: %ju Hz (Method B)\n",
|
||||
(intmax_t)tsc_freq);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if !defined(SMP)
|
||||
/*
|
||||
* We can not use the TSC in SMP mode, until we figure out a
|
||||
* cheap (impossible), reliable and precise (yeah right!) way
|
||||
* to synchronize the TSCs of all the CPUs.
|
||||
* Curse Intel for leaving the counter out of the I/O APIC.
|
||||
*/
|
||||
|
||||
/*
|
||||
* We can not use the TSC if we support APM. Precise timekeeping
|
||||
* on an APM'ed machine is at best a fools pursuit, since
|
||||
* any and all of the time spent in various SMM code can't
|
||||
* be reliably accounted for. Reading the RTC is your only
|
||||
* source of reliable time info. The i8254 looses too of course
|
||||
* but we need to have some kind of time...
|
||||
* We don't know at this point whether APM is going to be used
|
||||
* or not, nor when it might be activated. Play it safe.
|
||||
*/
|
||||
if (power_pm_get_type() == POWER_PM_TYPE_APM) {
|
||||
if (bootverbose)
|
||||
printf("TSC initialization skipped: APM enabled.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (tsc_present && tsc_freq != 0 && !tsc_is_broken) {
|
||||
tsc_timecounter.tc_frequency = tsc_freq;
|
||||
tc_init(&tsc_timecounter);
|
||||
}
|
||||
|
||||
#endif /* !defined(SMP) */
|
||||
init_TSC();
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1218,26 +1131,6 @@ sysctl_machdep_i8254_freq(SYSCTL_HANDLER_ARGS)
|
||||
SYSCTL_PROC(_machdep, OID_AUTO, i8254_freq, CTLTYPE_INT | CTLFLAG_RW,
|
||||
0, sizeof(u_int), sysctl_machdep_i8254_freq, "IU", "");
|
||||
|
||||
static int
|
||||
sysctl_machdep_tsc_freq(SYSCTL_HANDLER_ARGS)
|
||||
{
|
||||
int error;
|
||||
uint64_t freq;
|
||||
|
||||
if (tsc_timecounter.tc_frequency == 0)
|
||||
return (EOPNOTSUPP);
|
||||
freq = tsc_freq;
|
||||
error = sysctl_handle_int(oidp, &freq, sizeof(freq), req);
|
||||
if (error == 0 && req->newptr != NULL) {
|
||||
tsc_freq = freq;
|
||||
tsc_timecounter.tc_frequency = tsc_freq;
|
||||
}
|
||||
return (error);
|
||||
}
|
||||
|
||||
SYSCTL_PROC(_machdep, OID_AUTO, tsc_freq, CTLTYPE_QUAD | CTLFLAG_RW,
|
||||
0, sizeof(u_int), sysctl_machdep_tsc_freq, "IU", "");
|
||||
|
||||
static unsigned
|
||||
i8254_get_timecount(struct timecounter *tc)
|
||||
{
|
||||
@ -1274,12 +1167,6 @@ i8254_get_timecount(struct timecounter *tc)
|
||||
return (count);
|
||||
}
|
||||
|
||||
static unsigned
|
||||
tsc_get_timecount(struct timecounter *tc)
|
||||
{
|
||||
return (rdtsc());
|
||||
}
|
||||
|
||||
#ifdef DEV_ISA
|
||||
/*
|
||||
* Attach to the ISA PnP descriptors for the timer and realtime clock.
|
||||
|
Loading…
Reference in New Issue
Block a user