147e07394SAndrew Turner /*
247e07394SAndrew Turner * Copyright (C) 2015 Mihai Carabas <mihai.carabas@gmail.com>
347e07394SAndrew Turner * All rights reserved.
447e07394SAndrew Turner *
547e07394SAndrew Turner * Redistribution and use in source and binary forms, with or without
647e07394SAndrew Turner * modification, are permitted provided that the following conditions
747e07394SAndrew Turner * are met:
847e07394SAndrew Turner * 1. Redistributions of source code must retain the above copyright
947e07394SAndrew Turner * notice, this list of conditions and the following disclaimer.
1047e07394SAndrew Turner * 2. Redistributions in binary form must reproduce the above copyright
1147e07394SAndrew Turner * notice, this list of conditions and the following disclaimer in the
1247e07394SAndrew Turner * documentation and/or other materials provided with the distribution.
1347e07394SAndrew Turner *
1447e07394SAndrew Turner * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1547e07394SAndrew Turner * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1647e07394SAndrew Turner * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1747e07394SAndrew Turner * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
1847e07394SAndrew Turner * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1947e07394SAndrew Turner * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2047e07394SAndrew Turner * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2147e07394SAndrew Turner * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2247e07394SAndrew Turner * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2347e07394SAndrew Turner * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2447e07394SAndrew Turner * SUCH DAMAGE.
2547e07394SAndrew Turner */
2647e07394SAndrew Turner
2747e07394SAndrew Turner #ifndef _VMM_H_
2847e07394SAndrew Turner #define _VMM_H_
2947e07394SAndrew Turner
3047e07394SAndrew Turner #include <sys/param.h>
3147e07394SAndrew Turner #include <sys/cpuset.h>
3247e07394SAndrew Turner #include <vm/vm.h>
3347e07394SAndrew Turner #include <vm/pmap.h>
3447e07394SAndrew Turner
3547e07394SAndrew Turner #include "pte.h"
3647e07394SAndrew Turner #include "pmap.h"
3747e07394SAndrew Turner
3847e07394SAndrew Turner struct vcpu;
3947e07394SAndrew Turner
4047e07394SAndrew Turner enum vm_suspend_how {
4147e07394SAndrew Turner VM_SUSPEND_NONE,
4247e07394SAndrew Turner VM_SUSPEND_RESET,
4347e07394SAndrew Turner VM_SUSPEND_POWEROFF,
4447e07394SAndrew Turner VM_SUSPEND_HALT,
4547e07394SAndrew Turner VM_SUSPEND_LAST
4647e07394SAndrew Turner };
4747e07394SAndrew Turner
4847e07394SAndrew Turner /*
4947e07394SAndrew Turner * Identifiers for architecturally defined registers.
5047e07394SAndrew Turner */
5147e07394SAndrew Turner enum vm_reg_name {
5247e07394SAndrew Turner VM_REG_GUEST_X0 = 0,
5347e07394SAndrew Turner VM_REG_GUEST_X1,
5447e07394SAndrew Turner VM_REG_GUEST_X2,
5547e07394SAndrew Turner VM_REG_GUEST_X3,
5647e07394SAndrew Turner VM_REG_GUEST_X4,
5747e07394SAndrew Turner VM_REG_GUEST_X5,
5847e07394SAndrew Turner VM_REG_GUEST_X6,
5947e07394SAndrew Turner VM_REG_GUEST_X7,
6047e07394SAndrew Turner VM_REG_GUEST_X8,
6147e07394SAndrew Turner VM_REG_GUEST_X9,
6247e07394SAndrew Turner VM_REG_GUEST_X10,
6347e07394SAndrew Turner VM_REG_GUEST_X11,
6447e07394SAndrew Turner VM_REG_GUEST_X12,
6547e07394SAndrew Turner VM_REG_GUEST_X13,
6647e07394SAndrew Turner VM_REG_GUEST_X14,
6747e07394SAndrew Turner VM_REG_GUEST_X15,
6847e07394SAndrew Turner VM_REG_GUEST_X16,
6947e07394SAndrew Turner VM_REG_GUEST_X17,
7047e07394SAndrew Turner VM_REG_GUEST_X18,
7147e07394SAndrew Turner VM_REG_GUEST_X19,
7247e07394SAndrew Turner VM_REG_GUEST_X20,
7347e07394SAndrew Turner VM_REG_GUEST_X21,
7447e07394SAndrew Turner VM_REG_GUEST_X22,
7547e07394SAndrew Turner VM_REG_GUEST_X23,
7647e07394SAndrew Turner VM_REG_GUEST_X24,
7747e07394SAndrew Turner VM_REG_GUEST_X25,
7847e07394SAndrew Turner VM_REG_GUEST_X26,
7947e07394SAndrew Turner VM_REG_GUEST_X27,
8047e07394SAndrew Turner VM_REG_GUEST_X28,
8147e07394SAndrew Turner VM_REG_GUEST_X29,
8247e07394SAndrew Turner VM_REG_GUEST_LR,
8347e07394SAndrew Turner VM_REG_GUEST_SP,
8447e07394SAndrew Turner VM_REG_GUEST_PC,
8547e07394SAndrew Turner VM_REG_GUEST_CPSR,
8647e07394SAndrew Turner
8747e07394SAndrew Turner VM_REG_GUEST_SCTLR_EL1,
8847e07394SAndrew Turner VM_REG_GUEST_TTBR0_EL1,
8947e07394SAndrew Turner VM_REG_GUEST_TTBR1_EL1,
9047e07394SAndrew Turner VM_REG_GUEST_TCR_EL1,
9147e07394SAndrew Turner VM_REG_GUEST_TCR2_EL1,
9247e07394SAndrew Turner VM_REG_LAST
9347e07394SAndrew Turner };
9447e07394SAndrew Turner
9547e07394SAndrew Turner #define VM_INTINFO_VECTOR(info) ((info) & 0xff)
9647e07394SAndrew Turner #define VM_INTINFO_DEL_ERRCODE 0x800
9747e07394SAndrew Turner #define VM_INTINFO_RSVD 0x7ffff000
9847e07394SAndrew Turner #define VM_INTINFO_VALID 0x80000000
9947e07394SAndrew Turner #define VM_INTINFO_TYPE 0x700
10047e07394SAndrew Turner #define VM_INTINFO_HWINTR (0 << 8)
10147e07394SAndrew Turner #define VM_INTINFO_NMI (2 << 8)
10247e07394SAndrew Turner #define VM_INTINFO_HWEXCEPTION (3 << 8)
10347e07394SAndrew Turner #define VM_INTINFO_SWINTR (4 << 8)
10447e07394SAndrew Turner
10547e07394SAndrew Turner #define VM_MAX_SUFFIXLEN 15
10647e07394SAndrew Turner
10747e07394SAndrew Turner #define VM_GUEST_BASE_IPA 0x80000000UL /* Guest kernel start ipa */
10847e07394SAndrew Turner
10947e07394SAndrew Turner #ifdef _KERNEL
11047e07394SAndrew Turner
11147e07394SAndrew Turner #define VM_MAX_NAMELEN 32
11247e07394SAndrew Turner
11347e07394SAndrew Turner struct vm;
11447e07394SAndrew Turner struct vm_exception;
11547e07394SAndrew Turner struct vm_exit;
11647e07394SAndrew Turner struct vm_run;
11747e07394SAndrew Turner struct vm_object;
11847e07394SAndrew Turner struct vm_guest_paging;
11947e07394SAndrew Turner struct vm_vgic_descr;
12047e07394SAndrew Turner struct pmap;
12147e07394SAndrew Turner
12247e07394SAndrew Turner struct vm_eventinfo {
12347e07394SAndrew Turner void *rptr; /* rendezvous cookie */
12447e07394SAndrew Turner int *sptr; /* suspend cookie */
12547e07394SAndrew Turner int *iptr; /* reqidle cookie */
12647e07394SAndrew Turner };
12747e07394SAndrew Turner
12847e07394SAndrew Turner int vm_create(const char *name, struct vm **retvm);
12947e07394SAndrew Turner struct vcpu *vm_alloc_vcpu(struct vm *vm, int vcpuid);
13047e07394SAndrew Turner void vm_slock_vcpus(struct vm *vm);
13147e07394SAndrew Turner void vm_unlock_vcpus(struct vm *vm);
13247e07394SAndrew Turner void vm_destroy(struct vm *vm);
13347e07394SAndrew Turner int vm_reinit(struct vm *vm);
13447e07394SAndrew Turner const char *vm_name(struct vm *vm);
13547e07394SAndrew Turner
13647e07394SAndrew Turner /*
13747e07394SAndrew Turner * APIs that modify the guest memory map require all vcpus to be frozen.
13847e07394SAndrew Turner */
13947e07394SAndrew Turner void vm_slock_memsegs(struct vm *vm);
14047e07394SAndrew Turner void vm_xlock_memsegs(struct vm *vm);
14147e07394SAndrew Turner void vm_unlock_memsegs(struct vm *vm);
14247e07394SAndrew Turner int vm_mmap_memseg(struct vm *vm, vm_paddr_t gpa, int segid, vm_ooffset_t off,
14347e07394SAndrew Turner size_t len, int prot, int flags);
14447e07394SAndrew Turner int vm_munmap_memseg(struct vm *vm, vm_paddr_t gpa, size_t len);
14547e07394SAndrew Turner int vm_alloc_memseg(struct vm *vm, int ident, size_t len, bool sysmem);
14647e07394SAndrew Turner void vm_free_memseg(struct vm *vm, int ident);
14747e07394SAndrew Turner
14847e07394SAndrew Turner /*
14947e07394SAndrew Turner * APIs that inspect the guest memory map require only a *single* vcpu to
15047e07394SAndrew Turner * be frozen. This acts like a read lock on the guest memory map since any
15147e07394SAndrew Turner * modification requires *all* vcpus to be frozen.
15247e07394SAndrew Turner */
15347e07394SAndrew Turner int vm_mmap_getnext(struct vm *vm, vm_paddr_t *gpa, int *segid,
15447e07394SAndrew Turner vm_ooffset_t *segoff, size_t *len, int *prot, int *flags);
15547e07394SAndrew Turner int vm_get_memseg(struct vm *vm, int ident, size_t *len, bool *sysmem,
15647e07394SAndrew Turner struct vm_object **objptr);
15747e07394SAndrew Turner vm_paddr_t vmm_sysmem_maxaddr(struct vm *vm);
15847e07394SAndrew Turner void *vm_gpa_hold(struct vcpu *vcpu, vm_paddr_t gpa, size_t len,
15947e07394SAndrew Turner int prot, void **cookie);
16047e07394SAndrew Turner void *vm_gpa_hold_global(struct vm *vm, vm_paddr_t gpa, size_t len,
16147e07394SAndrew Turner int prot, void **cookie);
16247e07394SAndrew Turner void vm_gpa_release(void *cookie);
16347e07394SAndrew Turner bool vm_mem_allocated(struct vcpu *vcpu, vm_paddr_t gpa);
16447e07394SAndrew Turner
16547e07394SAndrew Turner int vm_gla2gpa_nofault(struct vcpu *vcpu, struct vm_guest_paging *paging,
16647e07394SAndrew Turner uint64_t gla, int prot, uint64_t *gpa, int *is_fault);
16747e07394SAndrew Turner
16847e07394SAndrew Turner uint16_t vm_get_maxcpus(struct vm *vm);
16947e07394SAndrew Turner void vm_get_topology(struct vm *vm, uint16_t *sockets, uint16_t *cores,
17047e07394SAndrew Turner uint16_t *threads, uint16_t *maxcpus);
17147e07394SAndrew Turner int vm_set_topology(struct vm *vm, uint16_t sockets, uint16_t cores,
17247e07394SAndrew Turner uint16_t threads, uint16_t maxcpus);
17347e07394SAndrew Turner int vm_get_register(struct vcpu *vcpu, int reg, uint64_t *retval);
17447e07394SAndrew Turner int vm_set_register(struct vcpu *vcpu, int reg, uint64_t val);
17547e07394SAndrew Turner int vm_run(struct vcpu *vcpu);
17647e07394SAndrew Turner int vm_suspend(struct vm *vm, enum vm_suspend_how how);
17747e07394SAndrew Turner void* vm_get_cookie(struct vm *vm);
17847e07394SAndrew Turner int vcpu_vcpuid(struct vcpu *vcpu);
17947e07394SAndrew Turner void *vcpu_get_cookie(struct vcpu *vcpu);
18047e07394SAndrew Turner struct vm *vcpu_vm(struct vcpu *vcpu);
18147e07394SAndrew Turner struct vcpu *vm_vcpu(struct vm *vm, int cpu);
18247e07394SAndrew Turner int vm_get_capability(struct vcpu *vcpu, int type, int *val);
18347e07394SAndrew Turner int vm_set_capability(struct vcpu *vcpu, int type, int val);
18447e07394SAndrew Turner int vm_activate_cpu(struct vcpu *vcpu);
18547e07394SAndrew Turner int vm_suspend_cpu(struct vm *vm, struct vcpu *vcpu);
18647e07394SAndrew Turner int vm_resume_cpu(struct vm *vm, struct vcpu *vcpu);
18747e07394SAndrew Turner int vm_inject_exception(struct vcpu *vcpu, uint64_t esr, uint64_t far);
18847e07394SAndrew Turner int vm_attach_vgic(struct vm *vm, struct vm_vgic_descr *descr);
18947e07394SAndrew Turner int vm_assert_irq(struct vm *vm, uint32_t irq);
19047e07394SAndrew Turner int vm_deassert_irq(struct vm *vm, uint32_t irq);
19147e07394SAndrew Turner int vm_raise_msi(struct vm *vm, uint64_t msg, uint64_t addr, int bus, int slot,
19247e07394SAndrew Turner int func);
19347e07394SAndrew Turner struct vm_exit *vm_exitinfo(struct vcpu *vcpu);
19447e07394SAndrew Turner void vm_exit_suspended(struct vcpu *vcpu, uint64_t pc);
19547e07394SAndrew Turner void vm_exit_debug(struct vcpu *vcpu, uint64_t pc);
19647e07394SAndrew Turner void vm_exit_rendezvous(struct vcpu *vcpu, uint64_t pc);
19747e07394SAndrew Turner void vm_exit_astpending(struct vcpu *vcpu, uint64_t pc);
19847e07394SAndrew Turner
19947e07394SAndrew Turner cpuset_t vm_active_cpus(struct vm *vm);
20047e07394SAndrew Turner cpuset_t vm_debug_cpus(struct vm *vm);
20147e07394SAndrew Turner cpuset_t vm_suspended_cpus(struct vm *vm);
20247e07394SAndrew Turner
20347e07394SAndrew Turner static __inline bool
virt_enabled(void)20447e07394SAndrew Turner virt_enabled(void)
20547e07394SAndrew Turner {
20647e07394SAndrew Turner
20747e07394SAndrew Turner return (has_hyp());
20847e07394SAndrew Turner }
20947e07394SAndrew Turner
21047e07394SAndrew Turner static __inline int
vcpu_rendezvous_pending(struct vm_eventinfo * info)21147e07394SAndrew Turner vcpu_rendezvous_pending(struct vm_eventinfo *info)
21247e07394SAndrew Turner {
21347e07394SAndrew Turner
21447e07394SAndrew Turner return (*((uintptr_t *)(info->rptr)) != 0);
21547e07394SAndrew Turner }
21647e07394SAndrew Turner
21747e07394SAndrew Turner static __inline int
vcpu_suspended(struct vm_eventinfo * info)21847e07394SAndrew Turner vcpu_suspended(struct vm_eventinfo *info)
21947e07394SAndrew Turner {
22047e07394SAndrew Turner
22147e07394SAndrew Turner return (*info->sptr);
22247e07394SAndrew Turner }
22347e07394SAndrew Turner
22447e07394SAndrew Turner int vcpu_debugged(struct vcpu *vcpu);
22547e07394SAndrew Turner
22647e07394SAndrew Turner enum vcpu_state {
22747e07394SAndrew Turner VCPU_IDLE,
22847e07394SAndrew Turner VCPU_FROZEN,
22947e07394SAndrew Turner VCPU_RUNNING,
23047e07394SAndrew Turner VCPU_SLEEPING,
23147e07394SAndrew Turner };
23247e07394SAndrew Turner
23347e07394SAndrew Turner int vcpu_set_state(struct vcpu *vcpu, enum vcpu_state state, bool from_idle);
23447e07394SAndrew Turner enum vcpu_state vcpu_get_state(struct vcpu *vcpu, int *hostcpu);
23547e07394SAndrew Turner
23647e07394SAndrew Turner static int __inline
vcpu_is_running(struct vcpu * vcpu,int * hostcpu)23747e07394SAndrew Turner vcpu_is_running(struct vcpu *vcpu, int *hostcpu)
23847e07394SAndrew Turner {
23947e07394SAndrew Turner return (vcpu_get_state(vcpu, hostcpu) == VCPU_RUNNING);
24047e07394SAndrew Turner }
24147e07394SAndrew Turner
24247e07394SAndrew Turner #ifdef _SYS_PROC_H_
24347e07394SAndrew Turner static int __inline
vcpu_should_yield(struct vcpu * vcpu)24447e07394SAndrew Turner vcpu_should_yield(struct vcpu *vcpu)
24547e07394SAndrew Turner {
24647e07394SAndrew Turner struct thread *td;
24747e07394SAndrew Turner
24847e07394SAndrew Turner td = curthread;
24947e07394SAndrew Turner return (td->td_ast != 0 || td->td_owepreempt != 0);
25047e07394SAndrew Turner }
25147e07394SAndrew Turner #endif
25247e07394SAndrew Turner
25347e07394SAndrew Turner void *vcpu_stats(struct vcpu *vcpu);
25447e07394SAndrew Turner void vcpu_notify_event(struct vcpu *vcpu);
25547e07394SAndrew Turner
25647e07394SAndrew Turner enum vm_reg_name vm_segment_name(int seg_encoding);
25747e07394SAndrew Turner
25847e07394SAndrew Turner struct vm_copyinfo {
25947e07394SAndrew Turner uint64_t gpa;
26047e07394SAndrew Turner size_t len;
26147e07394SAndrew Turner void *hva;
26247e07394SAndrew Turner void *cookie;
26347e07394SAndrew Turner };
26447e07394SAndrew Turner
26547e07394SAndrew Turner #endif /* _KERNEL */
26647e07394SAndrew Turner
26747e07394SAndrew Turner #define VM_DIR_READ 0
26847e07394SAndrew Turner #define VM_DIR_WRITE 1
26947e07394SAndrew Turner
27047e07394SAndrew Turner #define VM_GP_M_MASK 0x1f
27147e07394SAndrew Turner #define VM_GP_MMU_ENABLED (1 << 5)
27247e07394SAndrew Turner
27347e07394SAndrew Turner struct vm_guest_paging {
27447e07394SAndrew Turner uint64_t ttbr0_addr;
27547e07394SAndrew Turner uint64_t ttbr1_addr;
27647e07394SAndrew Turner uint64_t tcr_el1;
27747e07394SAndrew Turner uint64_t tcr2_el1;
27847e07394SAndrew Turner int flags;
27947e07394SAndrew Turner int padding;
28047e07394SAndrew Turner };
28147e07394SAndrew Turner
28247e07394SAndrew Turner struct vie {
28347e07394SAndrew Turner uint8_t access_size:4, sign_extend:1, dir:1, unused:2;
28447e07394SAndrew Turner enum vm_reg_name reg;
28547e07394SAndrew Turner };
28647e07394SAndrew Turner
28747e07394SAndrew Turner struct vre {
28847e07394SAndrew Turner uint32_t inst_syndrome;
28947e07394SAndrew Turner uint8_t dir:1, unused:7;
29047e07394SAndrew Turner enum vm_reg_name reg;
29147e07394SAndrew Turner };
29247e07394SAndrew Turner
29347e07394SAndrew Turner /*
29447e07394SAndrew Turner * Identifiers for optional vmm capabilities
29547e07394SAndrew Turner */
29647e07394SAndrew Turner enum vm_cap_type {
29747e07394SAndrew Turner VM_CAP_HALT_EXIT,
29847e07394SAndrew Turner VM_CAP_MTRAP_EXIT,
29947e07394SAndrew Turner VM_CAP_PAUSE_EXIT,
30047e07394SAndrew Turner VM_CAP_UNRESTRICTED_GUEST,
30147e07394SAndrew Turner VM_CAP_MAX
30247e07394SAndrew Turner };
30347e07394SAndrew Turner
30447e07394SAndrew Turner enum vm_exitcode {
30547e07394SAndrew Turner VM_EXITCODE_BOGUS,
30647e07394SAndrew Turner VM_EXITCODE_INST_EMUL,
30747e07394SAndrew Turner VM_EXITCODE_REG_EMUL,
30847e07394SAndrew Turner VM_EXITCODE_HVC,
30947e07394SAndrew Turner VM_EXITCODE_SUSPENDED,
31047e07394SAndrew Turner VM_EXITCODE_HYP,
31147e07394SAndrew Turner VM_EXITCODE_WFI,
31247e07394SAndrew Turner VM_EXITCODE_PAGING,
31347e07394SAndrew Turner VM_EXITCODE_SMCCC,
31447e07394SAndrew Turner VM_EXITCODE_DEBUG,
31547e07394SAndrew Turner VM_EXITCODE_MAX
31647e07394SAndrew Turner };
31747e07394SAndrew Turner
31847e07394SAndrew Turner struct vm_exit {
31947e07394SAndrew Turner enum vm_exitcode exitcode;
32047e07394SAndrew Turner int inst_length;
32147e07394SAndrew Turner uint64_t pc;
32247e07394SAndrew Turner union {
32347e07394SAndrew Turner /*
32447e07394SAndrew Turner * ARM specific payload.
32547e07394SAndrew Turner */
32647e07394SAndrew Turner struct {
32747e07394SAndrew Turner uint32_t exception_nr;
32847e07394SAndrew Turner uint32_t pad;
32947e07394SAndrew Turner uint64_t esr_el2; /* Exception Syndrome Register */
33047e07394SAndrew Turner uint64_t far_el2; /* Fault Address Register */
33147e07394SAndrew Turner uint64_t hpfar_el2; /* Hypervisor IPA Fault Address Register */
33247e07394SAndrew Turner } hyp;
33347e07394SAndrew Turner struct {
33447e07394SAndrew Turner struct vre vre;
33547e07394SAndrew Turner } reg_emul;
33647e07394SAndrew Turner struct {
33747e07394SAndrew Turner uint64_t gpa;
33847e07394SAndrew Turner uint64_t esr;
33947e07394SAndrew Turner } paging;
34047e07394SAndrew Turner struct {
34147e07394SAndrew Turner uint64_t gpa;
34247e07394SAndrew Turner struct vm_guest_paging paging;
34347e07394SAndrew Turner struct vie vie;
34447e07394SAndrew Turner } inst_emul;
34547e07394SAndrew Turner
34647e07394SAndrew Turner /*
34747e07394SAndrew Turner * A SMCCC call, e.g. starting a core via PSCI.
34847e07394SAndrew Turner * Further arguments can be read by asking the kernel for
34947e07394SAndrew Turner * all register values.
35047e07394SAndrew Turner */
35147e07394SAndrew Turner struct {
35247e07394SAndrew Turner uint64_t func_id;
35347e07394SAndrew Turner uint64_t args[7];
35447e07394SAndrew Turner } smccc_call;
35547e07394SAndrew Turner
35647e07394SAndrew Turner struct {
35747e07394SAndrew Turner enum vm_suspend_how how;
35847e07394SAndrew Turner } suspended;
35947e07394SAndrew Turner } u;
36047e07394SAndrew Turner };
36147e07394SAndrew Turner
36247e07394SAndrew Turner #endif /* _VMM_H_ */
363