Added the arch_cpu_idle() call to all platforms, though only x86 really
implements it yet (from freston). git-svn-id: file:///srv/svn/repos/haiku/trunk/current@307 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -2,17 +2,28 @@
|
|||||||
** Copyright 2001, Travis Geiselbrecht. All rights reserved.
|
** Copyright 2001, Travis Geiselbrecht. All rights reserved.
|
||||||
** Distributed under the terms of the NewOS License.
|
** Distributed under the terms of the NewOS License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <kernel/arch/cpu.h>
|
#include <kernel/arch/cpu.h>
|
||||||
#include <kernel/debug.h>
|
#include <kernel/debug.h>
|
||||||
#include <boot/stage2.h>
|
#include <boot/stage2.h>
|
||||||
|
|
||||||
int arch_cpu_init(kernel_args *ka)
|
|
||||||
|
int
|
||||||
|
arch_cpu_init(kernel_args *ka)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int arch_cpu_init2(kernel_args *ka)
|
|
||||||
|
int
|
||||||
|
arch_cpu_init2(kernel_args *ka)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
arch_cpu_idle(void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,45 +2,60 @@
|
|||||||
** Copyright 2001, Travis Geiselbrecht. All rights reserved.
|
** Copyright 2001, Travis Geiselbrecht. All rights reserved.
|
||||||
** Distributed under the terms of the NewOS License.
|
** Distributed under the terms of the NewOS License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <kernel/kernel.h>
|
#include <kernel/kernel.h>
|
||||||
#include <kernel/arch/cpu.h>
|
#include <kernel/arch/cpu.h>
|
||||||
#include <boot/stage2.h>
|
#include <boot/stage2.h>
|
||||||
|
|
||||||
int arch_cpu_init(kernel_args *ka)
|
|
||||||
|
int
|
||||||
|
arch_cpu_init(kernel_args *ka)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int arch_cpu_init2(kernel_args *ka)
|
|
||||||
|
int
|
||||||
|
arch_cpu_init2(kernel_args *ka)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void arch_cpu_invalidate_TLB_range(addr start, addr end)
|
|
||||||
|
void
|
||||||
|
arch_cpu_invalidate_TLB_range(addr start, addr end)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void arch_cpu_invalidate_TLB_list(addr pages[], int num_pages)
|
|
||||||
|
void
|
||||||
|
arch_cpu_invalidate_TLB_list(addr pages[], int num_pages)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void arch_cpu_global_TLB_invalidate(void)
|
|
||||||
|
void
|
||||||
|
arch_cpu_global_TLB_invalidate(void)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
long long system_time(void)
|
|
||||||
|
long long
|
||||||
|
system_time(void)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int arch_cpu_user_memcpy(void *to, const void *from, size_t size, addr *fault_handler)
|
|
||||||
|
int
|
||||||
|
arch_cpu_user_memcpy(void *to, const void *from, size_t size, addr *fault_handler)
|
||||||
{
|
{
|
||||||
char *tmp = (char *)to;
|
char *tmp = (char *)to;
|
||||||
char *s = (char *)from;
|
char *s = (char *)from;
|
||||||
|
|
||||||
*fault_handler = (addr)&&error;
|
*fault_handler = (addr)&&error;
|
||||||
|
|
||||||
while(size--)
|
while (size--)
|
||||||
*tmp++ = *s++;
|
*tmp++ = *s++;
|
||||||
|
|
||||||
*fault_handler = 0;
|
*fault_handler = 0;
|
||||||
@@ -51,11 +66,13 @@ error:
|
|||||||
return ERR_VM_BAD_USER_MEMORY;
|
return ERR_VM_BAD_USER_MEMORY;
|
||||||
}
|
}
|
||||||
|
|
||||||
int arch_cpu_user_strcpy(char *to, const char *from, addr *fault_handler)
|
|
||||||
|
int
|
||||||
|
arch_cpu_user_strcpy(char *to, const char *from, addr *fault_handler)
|
||||||
{
|
{
|
||||||
*fault_handler = (addr)&&error;
|
*fault_handler = (addr)&&error;
|
||||||
|
|
||||||
while((*to++ = *from++) != '\0')
|
while ((*to++ = *from++) != '\0')
|
||||||
;
|
;
|
||||||
|
|
||||||
*fault_handler = 0;
|
*fault_handler = 0;
|
||||||
@@ -66,11 +83,13 @@ error:
|
|||||||
return ERR_VM_BAD_USER_MEMORY;
|
return ERR_VM_BAD_USER_MEMORY;
|
||||||
}
|
}
|
||||||
|
|
||||||
int arch_cpu_user_strncpy(char *to, const char *from, size_t size, addr *fault_handler)
|
|
||||||
|
int
|
||||||
|
arch_cpu_user_strncpy(char *to, const char *from, size_t size, addr *fault_handler)
|
||||||
{
|
{
|
||||||
*fault_handler = (addr)&&error;
|
*fault_handler = (addr)&&error;
|
||||||
|
|
||||||
while(size-- && (*to++ = *from++) != '\0')
|
while (size-- && (*to++ = *from++) != '\0')
|
||||||
;
|
;
|
||||||
|
|
||||||
*fault_handler = 0;
|
*fault_handler = 0;
|
||||||
@@ -81,7 +100,9 @@ error:
|
|||||||
return ERR_VM_BAD_USER_MEMORY;
|
return ERR_VM_BAD_USER_MEMORY;
|
||||||
}
|
}
|
||||||
|
|
||||||
int arch_cpu_user_memset(void *s, char c, size_t count, addr *fault_handler)
|
|
||||||
|
int
|
||||||
|
arch_cpu_user_memset(void *s, char c, size_t count, addr *fault_handler)
|
||||||
{
|
{
|
||||||
char *xs = (char *) s;
|
char *xs = (char *) s;
|
||||||
|
|
||||||
@@ -99,3 +120,7 @@ error:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
arch_cpu_idle(void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
** Copyright 2001, Travis Geiselbrecht. All rights reserved.
|
** Copyright 2001, Travis Geiselbrecht. All rights reserved.
|
||||||
** Distributed under the terms of the NewOS License.
|
** Distributed under the terms of the NewOS License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <kernel/arch/cpu.h>
|
#include <kernel/arch/cpu.h>
|
||||||
#include <kernel/debug.h>
|
#include <kernel/debug.h>
|
||||||
#include <kernel/int.h>
|
#include <kernel/int.h>
|
||||||
@@ -9,12 +10,16 @@
|
|||||||
|
|
||||||
static vcpu_struct *vcpu;
|
static vcpu_struct *vcpu;
|
||||||
|
|
||||||
int arch_cpu_preboot_init(kernel_args *ka)
|
|
||||||
|
int
|
||||||
|
arch_cpu_preboot_init(kernel_args *ka)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int arch_cpu_init(kernel_args *ka)
|
|
||||||
|
int
|
||||||
|
arch_cpu_init(kernel_args *ka)
|
||||||
{
|
{
|
||||||
vcpu = ka->arch_args.vcpu;
|
vcpu = ka->arch_args.vcpu;
|
||||||
|
|
||||||
@@ -24,18 +29,24 @@ int arch_cpu_init(kernel_args *ka)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int arch_cpu_init2(kernel_args *ka)
|
|
||||||
|
int
|
||||||
|
arch_cpu_init2(kernel_args *ka)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void sh4_set_kstack(addr kstack)
|
|
||||||
|
void
|
||||||
|
sh4_set_kstack(addr kstack)
|
||||||
{
|
{
|
||||||
// dprintf("sh4_set_kstack: setting kstack to 0x%x\n", kstack);
|
// dprintf("sh4_set_kstack: setting kstack to 0x%x\n", kstack);
|
||||||
vcpu->kstack = (unsigned int *)kstack;
|
vcpu->kstack = (unsigned int *)kstack;
|
||||||
}
|
}
|
||||||
|
|
||||||
void sh4_set_user_pgdir(addr pgdir)
|
|
||||||
|
void
|
||||||
|
sh4_set_user_pgdir(addr pgdir)
|
||||||
{
|
{
|
||||||
// dprintf("sh4_set_user_pgdir: setting pgdir to 0x%x\n", pgdir);
|
// dprintf("sh4_set_user_pgdir: setting pgdir to 0x%x\n", pgdir);
|
||||||
if((addr)vcpu->user_pgdir != pgdir)
|
if((addr)vcpu->user_pgdir != pgdir)
|
||||||
@@ -43,7 +54,9 @@ void sh4_set_user_pgdir(addr pgdir)
|
|||||||
vcpu->user_pgdir = (unsigned int *)pgdir;
|
vcpu->user_pgdir = (unsigned int *)pgdir;
|
||||||
}
|
}
|
||||||
|
|
||||||
void sh4_invl_page(addr va)
|
|
||||||
|
void
|
||||||
|
sh4_invl_page(addr va)
|
||||||
{
|
{
|
||||||
int state;
|
int state;
|
||||||
int i;
|
int i;
|
||||||
@@ -69,14 +82,18 @@ void sh4_invl_page(addr va)
|
|||||||
int_restore_interrupts(state);
|
int_restore_interrupts(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
void arch_cpu_invalidate_TLB_range(addr start, addr end)
|
|
||||||
|
void
|
||||||
|
arch_cpu_invalidate_TLB_range(addr start, addr end)
|
||||||
{
|
{
|
||||||
for(; start < end; start += PAGE_SIZE) {
|
for(; start < end; start += PAGE_SIZE) {
|
||||||
sh4_invl_page(start);
|
sh4_invl_page(start);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void arch_cpu_invalidate_TLB_list(addr pages[], int num_pages)
|
|
||||||
|
void
|
||||||
|
arch_cpu_invalidate_TLB_list(addr pages[], int num_pages)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
for(i=0; i<num_pages; i++) {
|
for(i=0; i<num_pages; i++) {
|
||||||
@@ -84,7 +101,9 @@ void arch_cpu_invalidate_TLB_list(addr pages[], int num_pages)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void arch_cpu_global_TLB_invalidate()
|
|
||||||
|
void
|
||||||
|
arch_cpu_global_TLB_invalidate()
|
||||||
{
|
{
|
||||||
int state;
|
int state;
|
||||||
int i;
|
int i;
|
||||||
@@ -106,7 +125,9 @@ void arch_cpu_global_TLB_invalidate()
|
|||||||
int_restore_interrupts(state);
|
int_restore_interrupts(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
int arch_cpu_user_memcpy(void *to, const void *from, size_t size, addr *fault_handler)
|
|
||||||
|
int
|
||||||
|
arch_cpu_user_memcpy(void *to, const void *from, size_t size, addr *fault_handler)
|
||||||
{
|
{
|
||||||
char *tmp = (char *)to;
|
char *tmp = (char *)to;
|
||||||
char *s = (char *)from;
|
char *s = (char *)from;
|
||||||
@@ -124,7 +145,9 @@ error:
|
|||||||
return ERR_VM_BAD_USER_MEMORY;
|
return ERR_VM_BAD_USER_MEMORY;
|
||||||
}
|
}
|
||||||
|
|
||||||
int arch_cpu_user_strcpy(char *to, const char *from, addr *fault_handler)
|
|
||||||
|
int
|
||||||
|
arch_cpu_user_strcpy(char *to, const char *from, addr *fault_handler)
|
||||||
{
|
{
|
||||||
*fault_handler = (addr)&&error;
|
*fault_handler = (addr)&&error;
|
||||||
|
|
||||||
@@ -139,7 +162,9 @@ error:
|
|||||||
return ERR_VM_BAD_USER_MEMORY;
|
return ERR_VM_BAD_USER_MEMORY;
|
||||||
}
|
}
|
||||||
|
|
||||||
int arch_cpu_user_strncpy(char *to, const char *from, size_t size, addr *fault_handler)
|
|
||||||
|
int
|
||||||
|
arch_cpu_user_strncpy(char *to, const char *from, size_t size, addr *fault_handler)
|
||||||
{
|
{
|
||||||
*fault_handler = (addr)&&error;
|
*fault_handler = (addr)&&error;
|
||||||
|
|
||||||
@@ -154,7 +179,9 @@ error:
|
|||||||
return ERR_VM_BAD_USER_MEMORY;
|
return ERR_VM_BAD_USER_MEMORY;
|
||||||
}
|
}
|
||||||
|
|
||||||
int arch_cpu_user_memset(void *s, char c, size_t count, addr *fault_handler)
|
|
||||||
|
int
|
||||||
|
arch_cpu_user_memset(void *s, char c, size_t count, addr *fault_handler)
|
||||||
{
|
{
|
||||||
char *xs = (char *) s;
|
char *xs = (char *) s;
|
||||||
|
|
||||||
@@ -171,3 +198,8 @@ error:
|
|||||||
return ERR_VM_BAD_USER_MEMORY;
|
return ERR_VM_BAD_USER_MEMORY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
arch_cpu_idle(void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
** Copyright 2001-2002, Travis Geiselbrecht. All rights reserved.
|
** Copyright 2001-2002, Travis Geiselbrecht. All rights reserved.
|
||||||
** Distributed under the terms of the NewOS License.
|
** Distributed under the terms of the NewOS License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <kernel.h>
|
#include <kernel.h>
|
||||||
#include <arch/cpu.h>
|
#include <arch/cpu.h>
|
||||||
#include <memheap.h>
|
#include <memheap.h>
|
||||||
@@ -21,20 +22,26 @@ static int *tss_loaded;
|
|||||||
|
|
||||||
static unsigned int *gdt = 0;
|
static unsigned int *gdt = 0;
|
||||||
|
|
||||||
int arch_cpu_preboot_init(kernel_args *ka)
|
|
||||||
|
int
|
||||||
|
arch_cpu_preboot_init(kernel_args *ka)
|
||||||
{
|
{
|
||||||
write_dr3(0);
|
write_dr3(0);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int arch_cpu_init(kernel_args *ka)
|
|
||||||
|
int
|
||||||
|
arch_cpu_init(kernel_args *ka)
|
||||||
{
|
{
|
||||||
setup_system_time(ka->arch_args.system_time_cv_factor);
|
setup_system_time(ka->arch_args.system_time_cv_factor);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int arch_cpu_init2(kernel_args *ka)
|
|
||||||
|
int
|
||||||
|
arch_cpu_init2(kernel_args *ka)
|
||||||
{
|
{
|
||||||
region_id rid;
|
region_id rid;
|
||||||
struct tss_descriptor *tss_d;
|
struct tss_descriptor *tss_d;
|
||||||
@@ -46,13 +53,13 @@ int arch_cpu_init2(kernel_args *ka)
|
|||||||
REGION_ADDR_EXACT_ADDRESS, PAGE_SIZE, REGION_WIRING_WIRED_ALREADY, LOCK_RW|LOCK_KERNEL);
|
REGION_ADDR_EXACT_ADDRESS, PAGE_SIZE, REGION_WIRING_WIRED_ALREADY, LOCK_RW|LOCK_KERNEL);
|
||||||
|
|
||||||
tss = kmalloc(sizeof(struct tss *) * ka->num_cpus);
|
tss = kmalloc(sizeof(struct tss *) * ka->num_cpus);
|
||||||
if(tss == NULL) {
|
if (tss == NULL) {
|
||||||
panic("arch_cpu_init2: could not allocate buffer for tss pointers\n");
|
panic("arch_cpu_init2: could not allocate buffer for tss pointers\n");
|
||||||
return ENOMEM;
|
return ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
tss_loaded = kmalloc(sizeof(int) * ka->num_cpus);
|
tss_loaded = kmalloc(sizeof(int) * ka->num_cpus);
|
||||||
if(tss == NULL) {
|
if (tss == NULL) {
|
||||||
panic("arch_cpu_init2: could not allocate buffer for tss booleans\n");
|
panic("arch_cpu_init2: could not allocate buffer for tss booleans\n");
|
||||||
return ENOMEM;
|
return ENOMEM;
|
||||||
}
|
}
|
||||||
@@ -91,12 +98,14 @@ int arch_cpu_init2(kernel_args *ka)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void i386_set_kstack(addr kstack)
|
|
||||||
|
void
|
||||||
|
i386_set_kstack(addr kstack)
|
||||||
{
|
{
|
||||||
int curr_cpu = smp_get_current_cpu();
|
int curr_cpu = smp_get_current_cpu();
|
||||||
|
|
||||||
// dprintf("i386_set_kstack: kstack 0x%x, cpu %d\n", kstack, curr_cpu);
|
// dprintf("i386_set_kstack: kstack 0x%x, cpu %d\n", kstack, curr_cpu);
|
||||||
if(tss_loaded[curr_cpu] == 0) {
|
if (tss_loaded[curr_cpu] == 0) {
|
||||||
short seg = (0x28 + 8*curr_cpu);
|
short seg = (0x28 + 8*curr_cpu);
|
||||||
asm("movw %0, %%ax;"
|
asm("movw %0, %%ax;"
|
||||||
"ltr %%ax;" : : "r" (seg) : "eax");
|
"ltr %%ax;" : : "r" (seg) : "eax");
|
||||||
@@ -107,29 +116,35 @@ void i386_set_kstack(addr kstack)
|
|||||||
// dprintf("done\n");
|
// dprintf("done\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
void arch_cpu_invalidate_TLB_range(addr start, addr end)
|
|
||||||
|
void
|
||||||
|
arch_cpu_invalidate_TLB_range(addr start, addr end)
|
||||||
{
|
{
|
||||||
for(; start < end; start += PAGE_SIZE) {
|
for (; start < end; start += PAGE_SIZE) {
|
||||||
invalidate_TLB(start);
|
invalidate_TLB(start);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void arch_cpu_invalidate_TLB_list(addr pages[], int num_pages)
|
|
||||||
|
void
|
||||||
|
arch_cpu_invalidate_TLB_list(addr pages[], int num_pages)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
for(i=0; i<num_pages; i++) {
|
for (i = 0; i < num_pages; i++) {
|
||||||
invalidate_TLB(pages[i]);
|
invalidate_TLB(pages[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int arch_cpu_user_memcpy(void *to, const void *from, size_t size, addr *fault_handler)
|
|
||||||
|
int
|
||||||
|
arch_cpu_user_memcpy(void *to, const void *from, size_t size, addr *fault_handler)
|
||||||
{
|
{
|
||||||
char *tmp = (char *)to;
|
char *tmp = (char *)to;
|
||||||
char *s = (char *)from;
|
char *s = (char *)from;
|
||||||
|
|
||||||
*fault_handler = (addr)&&error;
|
*fault_handler = (addr)&&error;
|
||||||
|
|
||||||
while(size--)
|
while (size--)
|
||||||
*tmp++ = *s++;
|
*tmp++ = *s++;
|
||||||
|
|
||||||
*fault_handler = 0;
|
*fault_handler = 0;
|
||||||
@@ -140,11 +155,13 @@ error:
|
|||||||
return ERR_VM_BAD_USER_MEMORY;
|
return ERR_VM_BAD_USER_MEMORY;
|
||||||
}
|
}
|
||||||
|
|
||||||
int arch_cpu_user_strcpy(char *to, const char *from, addr *fault_handler)
|
|
||||||
|
int
|
||||||
|
arch_cpu_user_strcpy(char *to, const char *from, addr *fault_handler)
|
||||||
{
|
{
|
||||||
*fault_handler = (addr)&&error;
|
*fault_handler = (addr)&&error;
|
||||||
|
|
||||||
while((*to++ = *from++) != '\0')
|
while ((*to++ = *from++) != '\0')
|
||||||
;
|
;
|
||||||
|
|
||||||
*fault_handler = 0;
|
*fault_handler = 0;
|
||||||
@@ -155,7 +172,9 @@ error:
|
|||||||
return ERR_VM_BAD_USER_MEMORY;
|
return ERR_VM_BAD_USER_MEMORY;
|
||||||
}
|
}
|
||||||
|
|
||||||
int arch_cpu_user_strncpy(char *to, const char *from, size_t size, addr *fault_handler)
|
|
||||||
|
int
|
||||||
|
arch_cpu_user_strncpy(char *to, const char *from, size_t size, addr *fault_handler)
|
||||||
{
|
{
|
||||||
*fault_handler = (addr)&&error;
|
*fault_handler = (addr)&&error;
|
||||||
|
|
||||||
@@ -170,7 +189,9 @@ error:
|
|||||||
return ERR_VM_BAD_USER_MEMORY;
|
return ERR_VM_BAD_USER_MEMORY;
|
||||||
}
|
}
|
||||||
|
|
||||||
int arch_cpu_user_memset(void *s, char c, size_t count, addr *fault_handler)
|
|
||||||
|
int
|
||||||
|
arch_cpu_user_memset(void *s, char c, size_t count, addr *fault_handler)
|
||||||
{
|
{
|
||||||
char *xs = (char *) s;
|
char *xs = (char *) s;
|
||||||
|
|
||||||
@@ -187,3 +208,17 @@ error:
|
|||||||
return ERR_VM_BAD_USER_MEMORY;
|
return ERR_VM_BAD_USER_MEMORY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
arch_cpu_idle(void)
|
||||||
|
{
|
||||||
|
switch (smp_get_num_cpus()) {
|
||||||
|
case 0:
|
||||||
|
panic("You need at least 1 CPU to run NewOS\n");
|
||||||
|
case 1:
|
||||||
|
asm("hlt");
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user